;;; scheme-complete.el --- Smart tab completion for Emacs

;;; This code is written by Alex Shinn and placed in the Public
;;; Domain.  All warranties are disclaimed.

;;; This file provides a single function, `scheme-smart-complete',
;;; which you can use for intelligent, context-sensitive completion
;;; for any Scheme implementation.  To use it just load this file and
;;; bind that function to a key in your preferred mode:
;;;
;;; (autoload 'scheme-smart-complete "scheme-complete" nil t)
;;; (eval-after-load 'scheme
;;;   '(define-key scheme-mode-map "\e\t" 'scheme-smart-complete))
;;;
;;; Alternately, you may want to just bind TAB to the
;;; `scheme-complete-or-indent' function, which indents at the start
;;; of a line and otherwise performs the smart completion:
;;;
;;; (eval-after-load 'scheme
;;;   '(define-key scheme-mode-map "\t" 'scheme-complete-or-indent))
;;;
;;; If you use eldoc-mode (included in Emacs), you can also get live
;;; scheme documentation with:
;;;
;;; (autoload 'scheme-get-current-symbol-info "scheme-complete" nil t)
;;; (add-hook 'scheme-mode-hook
;;;   (lambda ()
;;;     (make-local-variable 'eldoc-documentation-function)
;;;     (setq eldoc-documentation-function 'scheme-get-current-symbol-info)
;;;     (eldoc-mode)))
;;;
;;; You can enable slightly smarter indentation with
;;;
;;; (setq lisp-indent-function 'scheme-smart-indent-function)
;;;
;;; which basically ignores the scheme-indent-function property for
;;; locally overridden symbols (e.g. if you use the (let loop () ...)
;;; idiom it won't use the special loop indentation inside).
;;;
;;; There's a single custom variable, `scheme-default-implementation',
;;; which you can use to specify your preferred implementation when we
;;; can't infer it from the source code.
;;;
;;; That's all there is to it.

;;; History:
;;; 0.8.3: 2008/10/06 - smart indent, inferring types from imported modules,
;;                      optionally caching exports, chicken 4 support
;;; 0.8.2: 2008/07/04 - both TAB and M-TAB scroll results (thanks Peter Bex),
;;;                     better MATCH handling, fixed SRFI-55, other bugfixes
;;; 0.8.1: 2008/04/17 - great renaming, everthing starts with `scheme-'
;;                      also, don't scan imported modules multiple times
;;;   0.8: 2008/02/08 - several parsing bugfixes on unclosed parenthesis
;;;                       (thanks to Kazushi NODA)
;;;                     filename completion works properly on absolute paths
;;;                     eldoc works properly on dotted lambdas
;;;   0.7: 2008/01/18 - handles higher-order types (for apply, map, etc.)
;;;                     smarter string completion (hostname, username, etc.)
;;;                     smarter type inference, various bugfixes
;;;   0.6: 2008/01/06 - more bugfixes (merry christmas)
;;;   0.5: 2008/01/03 - handling internal defines, records, smarter
;;;                     parsing
;;;   0.4: 2007/11/14 - silly bugfix plus better repo env support
;;;                     for searching chicken and gauche modules
;;;   0.3: 2007/11/13 - bugfixes, better inference, smart strings
;;;   0.2: 2007/10/15 - basic type inference
;;;   0.1: 2007/09/11 - initial release
;;;
;;;   What is this talk of 'release'? Klingons do not make software
;;;   'releases'. Our software 'escapes' leaving a bloody trail of
;;;   designers and quality assurance people in its wake.

(require 'cl)

;; this is just to eliminate some warnings when compiling - this file
;; should be loaded after 'scheme
(eval-when (compile)
  (require 'scheme))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; info
;;
;; identifier type [doc-string no-type-display?]
;;
;; types:
;;
;;   pair, number, symbol, etc.
;;   (lambda (param-types) [return-type])
;;   (syntax (param-types) [return-type])
;;   (set name values ...)
;;   (flags name values ...)
;;   (list type)
;;   (string expander)
;;   (special type function [outer-function])

(defvar *scheme-r5rs-info*
  '((define (syntax (identifier value) undefined) "define a new variable")
    (set! (syntax (identifier value) undefined) "set the value of a variable")
    (let (syntax (vars body \.\.\.)) "bind new local variables in parallel")
    (let* (syntax (vars body \.\.\.)) "bind new local variables sequentially")
    (letrec (syntax (vars body \.\.\.)) "bind new local variables recursively")
    (lambda (syntax (params body \.\.\.)) "procedure syntax")
    (if (syntax (cond then else)) "conditional evaluation")
    (cond (syntax (clause \.\.\.)) "try each clause until one succeeds")
    (case (syntax (expr clause \.\.\.)) "look for EXPR among literal lists")
    (delay (syntax (expr)) "create a promise to evaluate EXPR")
    (and (syntax (expr \.\.\.)) "evaluate EXPRs while true, return last")
    (or (syntax (expr \.\.\.)) "return the first true EXPR")
    (begin (syntax (expr \.\.\.)) "evaluate each EXPR in turn and return the last")
    (do (syntax (vars finish body \.\.\.)) "simple iterator")
    (quote (syntax (expr)) "represent EXPR literally without evaluating it")
    (quasiquote (syntax (expr)) "quote literals allowing escapes")
    (unquote (syntax (expr)) "escape an expression inside quasiquote")
    (unquote-splicing (syntax (expr)) "escape and splice a list expression inside quasiquote")
    (define-syntax (syntax (identifier body \.\.\.) undefined) "create a macro")
    (let-syntax (syntax (syntaxes body \.\.\.)) "a local macro")
    (letrec-syntax (syntax (syntaxes body \.\.\.)) "a local macro")
    (syntax-rules (syntax (literals clauses \.\.\.) undefined) "simple macro language")
    (eqv? (lambda (obj1 obj2) bool) "returns #t if OBJ1 and OBJ2 are the same object")
    (eq? (lambda (obj1 obj2) bool) "finer grained version of EQV?")
    (equal? (lambda (obj1 obj2) bool) "recursive equivalence")
    (not (lambda (obj) bool) "returns #t iff OBJ is false")
    (boolean? (lambda (obj) bool) "returns #t iff OBJ is #t or #f")
    (number? (lambda (obj) bool) "returns #t iff OBJ is a number")
    (complex? (lambda (obj) bool) "returns #t iff OBJ is a complex number")
    (real? (lambda (obj) bool) "returns #t iff OBJ is a real number")
    (rational? (lambda (obj) bool) "returns #t iff OBJ is a rational number")
    (integer? (lambda (obj) bool) "returns #t iff OBJ is an integer")
    (exact? (lambda (z) bool) "returns #t iff Z is exact")
    (inexact? (lambda (z) bool) "returns #t iff Z is inexact")
    (= (lambda (z1 z2 \.\.\.) bool) "returns #t iff the arguments are all equal")
    (< (lambda (x1 x2 \.\.\.) bool) "returns #t iff the arguments are monotonically increasing")
    (> (lambda (x1 x2 \.\.\.) bool) "returns #t iff the arguments are monotonically decreasing")
    (<= (lambda (x1 x2 \.\.\.) bool) "returns #t iff the arguments are monotonically nondecreasing")
    (>= (lambda (x1 x2 \.\.\.) bool) "returns #t iff the arguments are monotonically nonincreasing")
    (zero? (lambda (z) bool))
    (positive? (lambda (x1) bool))
    (negative? (lambda (x1) bool))
    (odd? (lambda (n) bool))
    (even? (lambda (n) bool))
    (max (lambda (x1 x2 \.\.\.) x3) "returns the maximum of the arguments")
    (min (lambda (x1 x2 \.\.\.) x3) "returns the minimum of the arguments")
    (+ (lambda (z1 \.\.\.) z))
    (* (lambda (z1 \.\.\.) z))
    (- (lambda (z1 \.\.\.) z))
    (/ (lambda (z1 \.\.\.) z))
    (abs (lambda (x1) x2) "returns the absolute value of X")
    (quotient (lambda (n1 n2) n) "integer division")
    (remainder (lambda (n1 n2) n) "same sign as N1")
    (modulo (lambda (n1 n2) n) "same sign as N2")
    (gcd (lambda (n1 \.\.\.) n) "greatest common divisor")
    (lcm (lambda (n2 \.\.\.) n) "least common multiple")
    (numerator (lambda (rational) n))
    (denominator (lambda (rational) n))
    (floor (lambda (x1) n) "largest integer not larger than X")
    (ceiling (lambda (x1) n) "smallest integer not smaller than X")
    (truncate (lambda (x1) n) "drop fractional part")
    (round (lambda (x1) n) "round to even (banker's rounding)")
    (rationalize (lambda (x1 y) n) "rational number differing from X by at most Y")
    (exp (lambda (z) z) "e^Z")
    (log (lambda (z) z) "natural logarithm of Z")
    (sin (lambda (z) z) "sine function")
    (cos (lambda (z) z) "cosine function")
    (tan (lambda (z) z) "tangent function")
    (asin (lambda (z) z) "arcsine function")
    (acos (lambda (z) z) "arccosine function")
    (atan (lambda (z) z) "arctangent function")
    (sqrt (lambda (z) z) "principal square root of Z")
    (expt (lambda (z1 z2) z) "returns Z1 raised to the Z2 power")
    (make-rectangular (lambda (x1 x2) z) "create a complex number")
    (make-polar (lambda (x1 x2) z) "create a complex number")
    (real-part (lambda (z) x1))
    (imag-part (lambda (z) x1))
    (magnitude (lambda (z) x1))
    (angle (lambda (z) x1))
    (exact->inexact (lambda (z) z))
    (inexact->exact (lambda (z) z))
    (number->string (lambda (z :optional radix) str))
    (string->number (lambda (str :optional radix) z))
    (pair? (lambda (obj) bool) "returns #t iff OBJ is a pair")
    (cons (lambda (obj1 obj2) pair) "create a newly allocated pair")
    (car (lambda (pair) obj))
    (cdr (lambda (pair) obj))
    (set-car! (lambda (pair obj) undefined))
    (set-cdr! (lambda (pair obj) undefined))
    (caar (lambda (pair) obj))
    (cadr (lambda (pair) obj))
    (cdar (lambda (pair) obj))
    (cddr (lambda (pair) obj))
    (caaar (lambda (pair) obj))
    (caadr (lambda (pair) obj))
    (cadar (lambda (pair) obj))
    (caddr (lambda (pair) obj))
    (cdaar (lambda (pair) obj))
    (cdadr (lambda (pair) obj))
    (cddar (lambda (pair) obj))
    (cdddr (lambda (pair) obj))
    (caaaar (lambda (pair) obj))
    (caaadr (lambda (pair) obj))
    (caadar (lambda (pair) obj))
    (caaddr (lambda (pair) obj))
    (cadaar (lambda (pair) obj))
    (cadadr (lambda (pair) obj))
    (caddar (lambda (pair) obj))
    (cadddr (lambda (pair) obj))
    (cdaaar (lambda (pair) obj))
    (cdaadr (lambda (pair) obj))
    (cdadar (lambda (pair) obj))
    (cdaddr (lambda (pair) obj))
    (cddaar (lambda (pair) obj))
    (cddadr (lambda (pair) obj))
    (cdddar (lambda (pair) obj))
    (cddddr (lambda (pair) obj))
    (null? (lambda (obj) bool) "returns #t iff OBJ is the empty list")
    (list? (lambda (obj) bool) "returns #t iff OBJ is a proper list")
    (list (lambda (obj \.\.\.) list) "returns a newly allocated list")
    (length (lambda (list) n))
    (append (lambda (list \.\.\.) list) "concatenates the list arguments")
    (reverse (lambda (list) list))
    (list-tail (lambda (list k) list) "returns the Kth cdr of LIST")
    (list-ref (lambda (list k) obj) "returns the Kth element of LIST")
    (memq (lambda (obj list)) "the sublist of LIST whose car is eq? to OBJ")
    (memv (lambda (obj list)) "the sublist of LIST whose car is eqv? to OBJ")
    (member (lambda (obj list)) "the sublist of LIST whose car is equal? to OBJ")
    (assq (lambda (obj list)) "the element of LIST whose car is eq? to OBJ")
    (assv (lambda (obj list)) "the element of LIST whose car is eqv? to OBJ")
    (assoc (lambda (obj list)) "the element of LIST whose car is equal? to OBJ")
    (symbol? (lambda (obj) bool) "returns #t iff OBJ is a symbol")
    (symbol->string (lambda (symbol) str))
    (string->symbol (lambda (str) symbol))
    (char? (lambda (obj) bool) "returns #t iff OBJ is a character")
    (char=? (lambda (ch1 ch2) bool))
    (char<? (lambda (ch1 ch2) bool))
    (char>? (lambda (ch1 ch2) bool))
    (char<=? (lambda (ch1 ch2) bool))
    (char>=? (lambda (ch1 ch2) bool))
    (char-ci=? (lambda (ch1 ch2) bool))
    (char-ci<? (lambda (ch1 ch2) bool))
    (char-ci>? (lambda (ch1 ch2) bool))
    (char-ci<=? (lambda (ch1 ch2) bool))
    (char-ci>=? (lambda (ch1 ch2) bool))
    (char-alphabetic? (lambda (ch) bool))
    (char-numeric? (lambda (ch) bool))
    (char-whitespace? (lambda (ch) bool))
    (char-upper-case? (lambda (ch) bool))
    (char-lower-case? (lambda (ch) bool))
    (char->integer (lambda (ch) int))
    (integer->char (lambda (int) ch))
    (char-upcase (lambda (ch) ch))
    (char-downcase (lambda (ch) ch))
    (string? (lambda (obj) bool) "returns #t iff OBJ is a string")
    (make-string (lambda (k :optional ch) str) "a new string of length k")
    (string (lambda (ch \.\.\.) str) "a new string made of the char arguments")
    (string-length (lambda (str) n) "the number of characters in STR")
    (string-ref (lambda (str i) ch) "the Ith character of STR")
    (string-set! (lambda (str i ch) undefined) "set the Ith character of STR to CH")
    (string=? (lambda (str1 str2) bool))
    (string-ci=? (lambda (str1 str2) bool))
    (string<? (lambda (str1 str2) bool))
    (string>? (lambda (str1 str2) bool))
    (string<=? (lambda (str1 str2) bool))
    (string>=? (lambda (str1 str2) bool))
    (string-ci<? (lambda (str1 str2) bool))
    (string-ci>? (lambda (str1 str2) bool))
    (string-ci<=? (lambda (str1 str2) bool))
    (string-ci>=? (lambda (str1 str2) bool))
    (substring (lambda (str start end) str))
    (string-append (lambda (str \.\.\.) str) "concatenate the string arguments")
    (string->list (lambda (str) list))
    (list->string (lambda (list) str))
    (string-copy (lambda (str) str))
    (string-fill! (lambda (str ch) undefined) "set every char in STR to CH")
    (vector? (lambda (obj) bool) "returns #t iff OBJ is a vector")
    (make-vector (lambda (len :optional fill) vec) "a new vector of K elements")
    (vector (lambda (obj \.\.\.) vec))
    (vector-length (lambda (vec) n) "the number of elements in VEC")
    (vector-ref (lambda (vec i) obj) "the Ith element of VEC")
    (vector-set! (lambda (vec i obj) undefined) "set the Ith element of VEC to OBJ")
    (vector->list (lambda (vec) list))
    (list->vector (lambda (list) vec))
    (vector-fill! (lambda (vec obj) undefined) "set every element in VEC to OBJ")
    (procedure? (lambda (obj) bool) "returns #t iff OBJ is a procedure")
    (apply (lambda ((lambda obj a) obj \.\.\.) a) "procedure application")
    (map (lambda ((lambda obj a) obj \.\.\.) (list a)) "a new list of PROC applied to every element of LIST")
    (for-each (lambda ((lambda obj a) obj \.\.\.) undefined) "apply PROC to each element of LIST in order")
    (force (lambda (promise) obj) "force the delayed value of PROMISE")
    (call-with-current-continuation (lambda (proc) obj) "goto on steroids")
    (values (lambda (obj \.\.\.)) "send multiple values to the calling continuation")
    (call-with-values (lambda (producer consumer) obj))
    (dynamic-wind (lambda (before-thunk thunk after-thunk) obj))
    (scheme-report-environment (lambda (int) env) "INT should be 5")
    (null-environment (lambda (int) env) "INT should be 5")
    (call-with-input-file (lambda (path proc) input-port))
    (call-with-output-file (lambda (path proc) output-port))
    (input-port? (lambda (obj) bool) "returns #t iff OBJ is an input port")
    (output-port? (lambda (obj) bool) "returns #t iff OBJ is an output port")
    (current-input-port (lambda () input-port) "the default input for read procedures")
    (current-output-port (lambda () output-port) "the default output for write procedures")
    (with-input-from-file (lambda (path thunk) obj))
    (with-output-to-file (lambda (path thunk) obj))
    (open-input-file (lambda (path) input-port))
    (open-output-file (lambda (path) output-port))
    (close-input-port (lambda (input-port)))
    (close-output-port (lambda (output-port)))
    (read (lambda (:optional input-port) obj) "read a datum")
    (read-char (lambda (:optional input-port) ch) "read a single character")
    (peek-char (lambda (:optional input-port) ch))
    (eof-object? (lambda (obj) bool) "returns #t iff OBJ is the end-of-file object")
    (char-ready? (lambda (:optional input-port) bool))
    (write (lambda (object :optional output-port) undefined) "write a datum")
    (display (lambda (object :optional output-port) undefined) "display")
    (newline (lambda (:optional output-port) undefined) "send a linefeed")
    (write-char (lambda (char :optional output-port) undefined) "write a single character")
    (load (lambda (filename) undefined) "evaluate expressions from a file")
    (eval (lambda (expr env)))
  ))

(defvar *scheme-srfi-info*
  [
   ;; SRFI 0
   ("Feature-based conditional expansion construct"
    (cond-expand (syntax (clause \.\.\.))))
   
   ;; SRFI 1
   ("List Library"
    (xcons (lambda (object object) pair))
    (cons* (lambda (object \.\.\.) pair))
    (make-list (lambda (integer :optional object) list))
    (list-tabulate (lambda (integer procedure) list))
    (list-copy (lambda (list) list))
    (circular-list (lambda (object \.\.\.) list))
    (iota (lambda (integer :optional integer integer) list))
    (proper-list? (lambda (object) bool))
    (circular-list? (lambda (object) bool))
    (dotted-list? (lambda (object) bool))
    (not-pair? (lambda (object) bool))
    (null-list? (lambda (object) bool))
    (list= (lambda (procedure list \.\.\.) bool))
    (first (lambda (pair)))
    (second (lambda (pair)))
    (third (lambda (pair)))
    (fourth (lambda (pair)))
    (fifth (lambda (pair)))
    (sixth (lambda (pair)))
    (seventh (lambda (pair)))
    (eighth (lambda (pair)))
    (ninth (lambda (pair)))
    (tenth (lambda (pair)))
    (car+cdr (lambda (pair)))
    (take (lambda (pair integer) list))
    (drop (lambda (pair integer) list))
    (take-right (lambda (pair integer) list))
    (drop-right (lambda (pair integer) list))
    (take! (lambda (pair integer) list))
    (drop-right! (lambda (pair integer) list))
    (split-at (lambda (pair integer) list))
    (split-at! (lambda (pair integer) list))
    (last (lambda (pair) obj))
    (last-pair (lambda (pair) pair))
    (length+ (lambda (object) n))
    (concatenate (lambda (list) list))
    (append! (lambda (list \.\.\.) list))
    (concatenate! (lambda (list) list))
    (reverse! (lambda (list) list))
    (append-reverse (lambda (list list) list))
    (append-reverse! (lambda (list list) list))
    (zip (lambda (list \.\.\.) list))
    (unzip1 (lambda (list) list))
    (unzip2 (lambda (list) list))
    (unzip3 (lambda (list) list))
    (unzip4 (lambda (list) list))
    (unzip5 (lambda (list) list))
    (count (lambda (procedure list \.\.\.) n))
    (fold (lambda ((lambda obj a) object list \.\.\.) a))
    (unfold (lambda (procedure procedure procedure object :optional procedure) obj))
    (pair-fold (lambda ((lambda obj a) object list \.\.\.) a))
    (reduce (lambda ((lambda obj a) object list \.\.\.) a))
    (fold-right (lambda ((lambda obj a) object list \.\.\.) a))
    (unfold-right (lambda (procedure procedure procedure object :optional object) obj))
    (pair-fold-right (lambda ((lambda obj a) object list \.\.\.) a))
    (reduce-right (lambda ((lambda obj a) object list \.\.\.) a))
    (append-map (lambda (procedure list \.\.\.) list))
    (append-map! (lambda (procedure list \.\.\.) list))
    (map! (lambda (procedure list \.\.\.) list))
    (pair-for-each (lambda (procedure list \.\.\.) undefined))
    (filter-map (lambda (procedure list \.\.\.) list))
    (map-in-order (lambda (procedure list \.\.\.) list))
    (filter (lambda (procedure list) list))
    (partition (lambda (procedure list) list))
    (remove (lambda (procedure list) list))
    (filter! (lambda (procedure list) list))
    (partition! (lambda (procedure list) list))
    (remove! (lambda (procedure list) list))
    (find (lambda (procedure list) obj))
    (find-tail (lambda (procedure list) obj))
    (any (lambda ((lambda obj a) list \.\.\.) a))
    (every (lambda ((lambda obj a) list \.\.\.) a))
    (list-index (lambda (procedure list \.\.\.) (or bool integer)))
    (take-while (lambda (procedure list) list))
    (drop-while (lambda (procedure list) list))
    (take-while! (lambda (procedure list) list))
    (span (lambda (procedure list) list))
    (break (lambda (procedure list) list))
    (span! (lambda (procedure list) list))
    (break! (lambda (procedure list) list))
    (delete (lambda (object list :optional procedure) list))
    (delete-duplicates (lambda (list :optional procedure) list))
    (delete! (lambda (obj list :optional procedure) list))
    (delete-duplicates! (lambda (list :optional procedure) list))
    (alist-cons (lambda (obj1 obj2 alist) alist))
    (alist-copy (lambda (alist) alist))
    (alist-delete (lambda (obj alist) alist))
    (alist-delete! (lambda (obj alist) alist))
    (lset<= (lambda (procedure list \.\.\.) bool))
    (lset= (lambda (procedure list \.\.\.) bool))
    (lset-adjoin (lambda (procedure list object \.\.\.) list))
    (lset-union (lambda (procedure list \.\.\.) list))
    (lset-union! (lambda (procedure list \.\.\.) list))
    (lset-intersection (lambda (procedure list \.\.\.) list))
    (lset-intersection! (lambda (procedure list \.\.\.) list))
    (lset-difference (lambda (procedure list \.\.\.) list))
    (lset-difference! (lambda (procedure list \.\.\.) list))
    (lset-xor (lambda (procedure list \.\.\.) list))
    (lset-xor! (lambda (procedure list \.\.\.) list))
    (lset-diff+intersection (lambda (procedure list \.\.\.) list))
    (lset-diff+intersection! (lambda (procedure list \.\.\.) list))

    )

   ;; SRFI 2
   ("AND-LET*: an AND with local bindings, a guarded LET* special form"
    (and-let* (syntax (bindings body \.\.\.))))

   ()

   ;; SRFI 4
   ("Homogeneous numeric vector datatypes"

    (u8vector? (lambda (obj) bool))
    (make-u8vector (lambda (size integer) u8vector))
    (u8vector (lambda (integer \.\.\.) u8vector))
    (u8vector-length (lambda (u8vector) n))
    (u8vector-ref (lambda (u8vector i) int))
    (u8vector-set! (lambda (u8vector i u8value) undefined))
    (u8vector->list (lambda (u8vector) list))
    (list->u8vector (lambda (list) u8vector))

    (s8vector? (lambda (obj) bool))
    (make-s8vector (lambda (size integer) s8vector))
    (s8vector (lambda (integer \.\.\.) s8vector))
    (s8vector-length (lambda (s8vector) n))
    (s8vector-ref (lambda (s8vector i) int))
    (s8vector-set! (lambda (s8vector i s8value) undefined))
    (s8vector->list (lambda (s8vector) list))
    (list->s8vector (lambda (list) s8vector))

    (u16vector? (lambda (obj) bool))
    (make-u16vector (lambda (size integer) u16vector))
    (u16vector (lambda (integer \.\.\.)))
    (u16vector-length (lambda (u16vector) n))
    (u16vector-ref (lambda (u16vector i) int))
    (u16vector-set! (lambda (u16vector i u16value) undefined))
    (u16vector->list (lambda (u16vector) list))
    (list->u16vector (lambda (list) u16vector))

    (s16vector? (lambda (obj) bool))
    (make-s16vector (lambda (size integer) s16vector))
    (s16vector (lambda (integer \.\.\.) s16vector))
    (s16vector-length (lambda (s16vector) n))
    (s16vector-ref (lambda (s16vector i) int))
    (s16vector-set! (lambda (s16vector i s16value) undefined))
    (s16vector->list (lambda (s16vector) list))
    (list->s16vector (lambda (list) s16vector))

    (u32vector? (lambda (obj) bool))
    (make-u32vector (lambda (size integer) u32vector))
    (u32vector (lambda (integer \.\.\.) u32vector))
    (u32vector-length (lambda (u32vector) n))
    (u32vector-ref (lambda (u32vector i) int))
    (u32vector-set! (lambda (u32vector i u32value) undefined))
    (u32vector->list (lambda (u32vector) list))
    (list->u32vector (lambda (list) u32vector))

    (s32vector? (lambda (obj) bool))
    (make-s32vector (lambda (size integer) s32vector))
    (s32vector (lambda (integer \.\.\.) s32vector))
    (s32vector-length (lambda (s32vector) n))
    (s32vector-ref (lambda (s32vector i) int))
    (s32vector-set! (lambda (s32vector i s32value) undefined))
    (s32vector->list (lambda (s32vector) list))
    (list->s32vector (lambda (list) s32vector))

    (u64vector? (lambda (obj) bool))
    (make-u64vector (lambda (size integer) u64vector))
    (u64vector (lambda (integer \.\.\.) u64vector))
    (u64vector-length (lambda (u64vector) n))
    (u64vector-ref (lambda (u64vector i) int))
    (u64vector-set! (lambda (u64vector i u64value) undefined))
    (u64vector->list (lambda (u64vector) list))
    (list->u64vector (lambda (list) u64vector))

    (s64vector? (lambda (obj) bool))
    (make-s64vector (lambda (size integer) s64vector))
    (s64vector (lambda (integer \.\.\.) s64vector))
    (s64vector-length (lambda (s64vector) n))
    (s64vector-ref (lambda (s64vector i) int))
    (s64vector-set! (lambda (s64vector i s64value) undefined))
    (s64vector->list (lambda (s64vector) list))
    (list->s64vector (lambda (list) s64vector))

    (f32vector? (lambda (obj) bool))
    (make-f32vector (lambda (size integer) f32vector))
    (f32vector (lambda (number \.\.\.) f32vector))
    (f32vector-length (lambda (f32vector) n))
    (f32vector-ref (lambda (f32vector i) int))
    (f32vector-set! (lambda (f32vector i f32value) undefined))
    (f32vector->list (lambda (f32vector) list))
    (list->f32vector (lambda (list) f32vector))

    (f64vector? (lambda (obj) bool))
    (make-f64vector (lambda (size integer) f64vector))
    (f64vector (lambda (number \.\.\.) f64vector))
    (f64vector-length (lambda (f64vector) n))
    (f64vector-ref (lambda (f64vector i) int))
    (f64vector-set! (lambda (f64vector i f64value) undefined))
    (f64vector->list (lambda (f64vector) list))
    (list->f64vector (lambda (list) f64vector))
    )

   ;; SRFI 5
   ("A compatible let form with signatures and rest arguments"
    (let (syntax (bindings body \.\.\.))))

   ;; SRFI 6
   ("Basic String Ports"
    (open-input-string (lambda (str) input-port))
    (open-output-string (lambda () output-port))
    (get-output-string (lambda (output-port) str)))

   ;; SRFI 7
   ("Feature-based program configuration language"
    (program (syntax (clause \.\.\.)))
    (feature-cond (syntax (clause))))

   ;; SRFI 8
   ("receive: Binding to multiple values"
    (receive (syntax (identifiers producer body \.\.\.))))

   ;; SRFI 9
   ("Defining Record Types"
    (define-record-type (syntax (name constructor-name pred-name fields \.\.\.))))

   ;; SRFI 10
   ("Sharp-Comma External Form"
    (define-reader-ctor (syntax (name proc) undefined)))

   ;; SRFI 11
   ("Syntax for receiving multiple values"
    (let-values (syntax (bindings body \.\.\.)))
    (let-values* (syntax (bindings body \.\.\.))))

   ()

   ;; SRFI 13
   ("String Library"
    (string-map (lambda (proc str :optional start end) str))
    (string-map! (lambda (proc str :optional start end) undefined))
    (string-fold (lambda (kons knil str :optional start end) obj))
    (string-fold-right (lambda (kons knil str :optional start end) obj))
    (string-unfold (lambda (p f g seed :optional base make-final) str))
    (string-unfold-right (lambda (p f g seed :optional base make-final) str))
    (string-tabulate (lambda (proc len) str))
    (string-for-each (lambda (proc str :optional start end) undefined))
    (string-for-each-index (lambda (proc str :optional start end) undefined))
    (string-every (lambda (pred str :optional start end) obj))
    (string-any (lambda (pred str :optional start end) obj))
    (string-hash (lambda (str :optional bound start end) int))
    (string-hash-ci (lambda (str :optional bound start end) int))
    (string-compare (lambda (string1 string2 lt-proc eq-proc gt-proc :optional start end) obj))
    (string-compare-ci (lambda (string1 string2 lt-proc eq-proc gt-proc :optional start end) obj))
    (string= (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string<> (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string< (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string> (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string<= (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string>= (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string-ci= (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string-ci<> (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string-ci< (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string-ci> (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string-ci<= (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string-ci>= (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string-titlecase (lambda (string :optional start end) str))
    (string-upcase (lambda (string :optional start end) str))
    (string-downcase (lambda (string :optional start end) str))
    (string-titlecase! (lambda (string :optional start end) undefined))
    (string-upcase! (lambda (string :optional start end) undefined))
    (string-downcase! (lambda (string :optional start end) undefined))
    (string-take (lambda (string nchars) str))
    (string-drop (lambda (string nchars) str))
    (string-take-right (lambda (string nchars) str))
    (string-drop-right (lambda (string nchars) str))
    (string-pad (lambda (string k :optional char start end) str))
    (string-pad-right (lambda (string k :optional char start end) str))
    (string-trim (lambda (string :optional char/char-set/pred start end) str))
    (string-trim-right (lambda (string :optional char/char-set/pred start end) str))
    (string-trim-both (lambda (string :optional char/char-set/pred start end) str))
    (string-filter (lambda (char/char-set/pred string :optional start end) str))
    (string-delete (lambda (char/char-set/pred string :optional start end) str))
    (string-index (lambda (string char/char-set/pred :optional start end) (or integer bool)))
    (string-index-right (lambda (string char/char-set/pred :optional end start) (or integer bool)))
    (string-skip (lambda (string char/char-set/pred :optional start end) (or integer bool)))
    (string-skip-right (lambda (string char/char-set/pred :optional end start) (or integer bool)))
    (string-count (lambda (string char/char-set/pred :optional start end) n))
    (string-prefix-length (lambda (string1 string2 :optional start1 end1 start2 end2) n))
    (string-suffix-length (lambda (string1 string2 :optional start1 end1 start2 end2) n))
    (string-prefix-length-ci (lambda (string1 string2 :optional start1 end1 start2 end2) n))
    (string-suffix-length-ci (lambda (string1 string2 :optional start1 end1 start2 end2) n))
    (string-prefix? (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string-suffix? (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string-prefix-ci? (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string-suffix-ci? (lambda (string1 string2 :optional start1 end1 start2 end2) bool))
    (string-contains (lambda (string pattern :optional s-start s-end p-start p-end) obj))
    (string-contains-ci (lambda (string pattern :optional s-start s-end p-start p-end) obj))
    (string-fill! (lambda (string char :optional start end) undefined))
    (string-copy! (lambda (to tstart from :optional fstart fend) undefined))
    (string-copy (lambda (str :optional start end) str))
    (substring/shared (lambda (str start :optional end) str))
    (string-reverse (lambda (str :optional start end) str))
    (string-reverse! (lambda (str :optional start end) undefined))
    (reverse-list->string (lambda (char-list) str))
    (string->list (lambda (str :optional start end) list))
    (string-concatenate (lambda (string-list) str))
    (string-concatenate/shared (lambda (string-list) str))
    (string-append/shared (lambda (str \.\.\.) str))
    (string-concatenate-reverse (lambda (string-list :optional final-string end) str))
    (string-concatenate-reverse/shared (lambda (string-list :optional final-string end) str))
    (xsubstring (lambda (str from :optional to start end) str))
    (string-xcopy! (lambda (target tstart str from :optional to start end) undefined))
    (string-null? (lambda (str) bool))
    (string-join (lambda (string-list :optional delim grammar) str))
    (string-tokenize (lambda (string :optional token-chars start end) str))
    (string-replace (lambda (str1 str2 start1 end1 :optional start2 end2) str))
    (string-kmp-partial-search (lambda (pat rv str i :optional c= p-start s-start s-end) n))
    (make-kmp-restart-vector (lambda (str :optional c= start end) vec))
    (kmp-step (lambda (pat rv c i c= p-start) n))
    )

   ;; SRFI 14
   ("Character-Set Library"
    (char-set? (lambda (cset) bool))
    (char-set= (lambda (cset \.\.\.) bool))
    (char-set<= (lambda (cset \.\.\.) bool))
    (char-set-hash (lambda (cset :optional int) int))
    (char-set-cursor (lambda (cset) cursor))
    (char-set-ref (lambda (cset cursor) ch))
    (char-set-cursor-next (lambda (cset cursor) int))
    (end-of-char-set? (lambda (cursor) bool))
    (char-set-fold (lambda (proc obj cset) obj))
    (char-set-unfold (lambda (proc proc proc obj :optional obj) cset))
    (char-set-unfold! (lambda (proc proc proc obj obj) cset))
    (char-set-for-each (lambda (proc cset) undefined))
    (char-set-map (lambda (proc cset) cset))
    (char-set-copy (lambda (cset) cset))
    (char-set (lambda (ch \.\.\.) cset))
    (list->char-set (lambda (list :optional obj) cset))
    (list->char-set! (lambda (list cset) cset))
    (string->char-set (lambda (str :optional cset) cset))
    (string->char-set! (lambda (str cset) cset))
    (ucs-range->char-set (lambda (int int :optional bool cset) cset))
    (ucs-range->char-set! (lambda (int int bool cset) cset))
    (char-set-filter (lambda (proc cset :optional base-cset) cset))
    (char-set-filter! (lambda (proc cset base-cset) cset))
    (->char-set (lambda (obj) cset))
    (char-set-size (lambda (cset) n))
    (char-set-count (lambda (proc cset) n))
    (char-set-contains? (lambda (cset ch) bool))
    (char-set-every (lambda (proc cset) obj))
    (char-set-any (lambda (proc cset) obj))
    (char-set-adjoin (lambda (cset ch \.\.\.) cset))
    (char-set-delete (lambda (cset ch \.\.\.) cset))
    (char-set-adjoin! (lambda (cset ch \.\.\.) cset))
    (char-set-delete! (lambda (cset ch \.\.\.) cset))
    (char-set->list (lambda (cset) list))
    (char-set->string (lambda (cset) str))
    (char-set-complement (lambda (cset) cset))
    (char-set-union (lambda (cset \.\.\.) cset))
    (char-set-intersection (lambda (cset \.\.\.) cset))
    (char-set-xor (lambda (cset \.\.\.) cset))
    (char-set-difference (lambda (cset \.\.\.) cset))
    (char-set-diff+intersection (lambda (cset \.\.\.) cset))
    (char-set-complement! (lambda (cset) cset))
    (char-set-union! (lambda (cset \.\.\.) cset))
    (char-set-intersection! (lambda (cset \.\.\.) cset))
    (char-set-xor! (lambda (cset \.\.\.) cset))
    (char-set-difference! (lambda (cset \.\.\.) cset))
    (char-set-diff+intersection! (lambda (cset \.\.\.) cset))
    (char-set:lower-case char-set)
    (char-set:upper-case char-set)
    (char-set:letter char-set)
    (char-set:digit char-set)
    (char-set:letter+digit char-set)
    (char-set:graphic char-set)
    (char-set:printing char-set)
    (char-set:whitespace char-set)
    (char-set:blank char-set)
    (char-set:iso-control char-set)
    (char-set:punctuation char-set)
    (char-set:symbol char-set)
    (char-set:hex-digit char-set)
    (char-set:ascii char-set)
    (char-set:empty char-set)
    (char-set:full char-set)
    )

   ()

   ;; SRFI 16
   ("Syntax for procedures of variable arity"
    (case-lambda (syntax (clauses \.\.\.) procedure)))

   ;; SRFI 17
   ("Generalized set!"
    (set! (syntax (what value) undefined)))

   ;; SRFI 18
   ("Multithreading support"
    (current-thread (lambda () thread))
    (thread? (lambda (obj) bool))
    (make-thread (lambda (thunk :optional name) thread))
    (thread-name (lambda (thread) name))
    (thread-specific (lambda (thread)))
    (thread-specific-set! (lambda (thread obj)))
    (thread-base-priority (lambda (thread)))
    (thread-base-priority-set! (lambda (thread number)))
    (thread-priority-boost (lambda (thread)))
    (thread-priority-boost-set! (lambda (thread number)))
    (thread-quantum (lambda (thread)))
    (thread-quantum-set! (lambda (thread number)))
    (thread-start! (lambda (thread)))
    (thread-yield! (lambda ()))
    (thread-sleep! (lambda (number)))
    (thread-terminate! (lambda (thread)))
    (thread-join! (lambda (thread :optional timeout timeout-val)))
    (mutex? (lambda (obj) bool))
    (make-mutex (lambda (:optional name) mutex))
    (mutex-name (lambda (mutex) name))
    (mutex-specific (lambda (mutex)))
    (mutex-specific-set! (lambda (mutex obj)))
    (mutex-state (lambda (mutex)))
    (mutex-lock! (lambda (mutex :optional timeout thread)))
    (mutex-unlock! (lambda (mutex :optional condition-variable timeout)))
    (condition-variable? (lambda (obj) bool))
    (make-condition-variable (lambda (:optional name) condition-variable))
    (condition-variable-name (lambda (condition-variable) name))
    (condition-variable-specific (lambda (condition-variable)))
    (condition-variable-specific-set! (lambda (condition-variable obj)))
    (condition-variable-signal! (lambda (condition-variable)))
    (condition-variable-broadcast! (lambda (condition-variable)))
    (current-time (lambda () time))
    (time? (lambda (obj) bool))
    (time->seconds (lambda (time) x1))
    (seconds->time (lambda (x1) time))
    (current-exception-handler (lambda () handler))
    (with-exception-handler (lambda (handler thunk)))
    (raise (lambda (obj)))
    (join-timeout-exception? (lambda (obj) bool))
    (abandoned-mutex-exception? (lambda (obj) bool))
    (terminated-thread-exception? (lambda (obj) bool))
    (uncaught-exception? (lambda (obj) bool))
    (uncaught-exception-reason (lambda (exc) obj))
    )

   ;; SRFI 19
   ("Time Data Types and Procedures"
    (current-date (lambda (:optional tz-offset)) date)
    (current-julian-day (lambda ()) jdn)
    (current-modified-julian-day (lambda ()) mjdn)
    (current-time (lambda (:optional time-type)) time)
    (time-resolution (lambda (:optional time-type)) nanoseconds)
    (make-time (lambda (type nanosecond second)))
    (time? (lambda (obj)))
    (time-type (lambda (time)))
    (time-nanosecond (lambda (time)))
    (time-second (lambda (time)))
    (set-time-type! (lambda (time)))
    (set-time-nanosecond! (lambda (time)))
    (set-time-second! (lambda (time)))
    (copy-time (lambda (time)))
    (time<=? (lambda (time1 time2)))
    (time<? (lambda (time1 time2)))
    (time=? (lambda (time1 time2)))
    (time>=? (lambda (time1 time2)))
    (time>? (lambda (time1 time2)))
    (time-difference (lambda (time1 time2)))
    (time-difference! (lambda (time1 time2)))
    (add-duration (lambda (time duration)))
    (add-duration! (lambda (time duration)))
    (subtract-duration (lambda (time duration)))
    (subtract-duration! (lambda (time duration)))
    (make-date (lambda (nanosecond second minute hour day month year zone-offset)))
    (date? (lambda (obj)))
    (date-nanosecond (lambda (date)))
    (date-second (lambda (date)))
    (date-minute (lambda (date)))
    (date-hour (lambda (date)))
    (date-day (lambda (date)))
    (date-month (lambda (date)))
    (date-year (lambda (date)))
    (date-zone-offset (lambda (date)))
    (date-year-day (lambda (date)))
    (date-week-day (lambda (date)))
    (date-week-number (lambda (date)))
    (date->julian-day (lambda (date)))
    (date->modified-julian-day (lambda (date)))
    (date->time-monotonic (lambda (date)))
    (date->time-tai (lambda (date)))
    (date->time-utc (lambda (date)))
    (julian-day->date (lambda (date)))
    (julian-day->time-monotonic (lambda (date)))
    (julian-day->time-tai (lambda (date)))
    (julian-day->time-utc (lambda (date)))
    (modified-julian-day->date (lambda (date)))
    (modified-julian-day->time-monotonic (lambda (date)))
    (modified-julian-day->time-tai (lambda (date)))
    (modified-julian-day->time-utc (lambda (date)))
    (time-monotonic->date (lambda (date)))
    (time-monotonic->julian-day (lambda (date)))
    (time-monotonic->modified-julian-day (lambda (date)))
    (time-monotonic->time-monotonic (lambda (date)))
    (time-monotonic->time-tai (lambda (date)))
    (time-monotonic->time-tai! (lambda (date)))
    (time-monotonic->time-utc (lambda (date)))
    (time-monotonic->time-utc! (lambda (date)))
    (time-tai->date (lambda (date)))
    (time-tai->julian-day (lambda (date)))
    (time-tai->modified-julian-day (lambda (date)))
    (time-tai->time-monotonic (lambda (date)))
    (time-tai->time-monotonic! (lambda (date)))
    (time-tai->time-utc (lambda (date)))
    (time-tai->time-utc! (lambda (date)))
    (time-utc->date (lambda (date)))
    (time-utc->julian-day (lambda (date)))
    (time-utc->modified-julian-day (lambda (date)))
    (time-utc->time-monotonic (lambda (date)))
    (time-utc->time-monotonic! (lambda (date)))
    (time-utc->time-tai (lambda (date)))
    (time-utc->time-tai! (lambda (date)))
    (date->string (lambda (date :optional format-string)))
    (string->date (lambda (input-string template-string)))
    )

   ()

   ;; SRFI 21
   ("Real-time multithreading support"
    srfi-18)                            ; same as srfi-18

   ;; SRFI 22
   ("Running Scheme Scripts on Unix"
    )

   ;; SRFI 23
   ("Error reporting mechanism"
    (error (lambda (reason-string arg \.\.\.))))

   ()

   ;; SRFI 25
   ("Multi-dimensional Array Primitives"
    (array? (lambda (obj)))
    (make-array (lambda (shape :optional init)))
    (shape (lambda (bound \.\.\.)))
    (array (lambda (shape obj \.\.\.)))
    (array-rank (lambda (array)))
    (array-start (lambda (array)))
    (array-end (lambda (array)))
    (array-shape (lambda (array)))
    (array-ref (lambda (array i \.\.\.)))
    (array-set! (lambda (array obj \.\.\.) undefined))
    (share-array (lambda (array shape proc)))
    )

   ;; SRFI 26
   ("Notation for Specializing Parameters without Currying"
    (cut (syntax (obj \.\.\.)))
    (cute (lambda (obj \.\.\.))))

   ;; SRFI 27
   ("Sources of Random Bits"
    (random-integer (lambda (n)))
    (random-real (lambda ()))
    (default-random-source (lambda ()))
    (make-random-source (lambda ()))
    (random-source? (lambda (obj)))
    (random-source-state-ref (lambda (random-source)))
    (random-source-state-set! (lambda (random-source state)))
    (random-source-randomize! (lambda (random-source)))
    (random-source-pseudo-randomize! (lambda (random-source i j)))
    (random-source-make-integers (lambda (random-source)))
    (random-source-make-reals (lambda (random-source)))
    )

   ;; SRFI 28
   ("Basic Format Strings"
    (format (lambda (port-or-boolean format-string arg \.\.\.))))

   ;; SRFI 29
   ("Localization"
    (current-language (lambda (:optional symbol)))
    (current-country (lambda (:optional symbol)))
    (current-locale-details (lambda (:optional list)))
    (declare-bundle! (lambda (bundle-name association-list)))
    (store-bundle (lambda (bundle-name)))
    (load-bundle! (lambda (bundle-name)))
    (localized-template (lambda (package-name message-template-name)))
    )

   ;; SRFI 30
   ("Nested Multi-line Comments"
    )

   ;; SRFI 31
   ("A special form for recursive evaluation"
    (rec (syntax (name body \.\.\.) procedure)))

   ()

   ()

   ;; SRFI 34
   ("Exception Handling for Programs"
    (guard (syntax (clauses \.\.\.)))
    (raise (lambda (obj)))
    )

   ;; SRFI 35
   ("Conditions"
    (make-condition-type (lambda (id parent field-name-list)))
    (condition-type? (lambda (obj)))
    (make-condition (lambda (condition-type)))
    (condition? (lambda (obj)))
    (condition-has-type? (lambda (condition condition-type)))
    (condition-ref (lambda (condition field-name)))
    (make-compound-condition (lambda (condition \.\.\.)))
    (extract-condition (lambda (condition condition-type)))
    (define-condition-type (syntax (name parent pred-name fields \.\.\.)))
    (condition (syntax (type-field-binding \.\.\.)))
    )

   ;; SRFI 36
   ("I/O Conditions"
    (&error condition)
    (&i/o-error condition)
    (&i/o-port-error condition)
    (&i/o-read-error condition)
    (&i/o-write-error condition)
    (&i/o-closed-error condition)
    (&i/o-filename-error condition)
    (&i/o-malformed-filename-error condition)
    (&i/o-file-protection-error condition)
    (&i/o-file-is-read-only-error condition)
    (&i/o-file-already-exists-error condition)
    (&i/o-no-such-file-error condition)
    )

   ;; SRFI 37
   ("args-fold: a program argument processor"
    (args-fold
     (arg-list option-list unrecognized-option-proc operand-proc seed \.\.\.))
    (option-processor (lambda (option name arg seeds \.\.\.)))
    (operand-processor (lambda (operand seeds \.\.\.)))
    (option (lambda (name-list required-arg? optional-arg? option-proc)))
    (option-names (lambda (option)))
    (option-required-arg? (lambda (option)))
    (option-optional-arg? (lambda (option)))
    (option-processor (lambda (option)))
    )

   ;; SRFI 38
   ("External Representation for Data With Shared Structure"
    (write-with-shared-structure (lambda (obj :optional port optarg)))
    (read-with-shared-structure (lambda (:optional port)))
    )

   ;; SRFI 39
   ("Parameter objects"
    (make-parameter (lambda (init-value :optional converter)))
    (parameterize (syntax (bindings body \.\.\.))))

   ;; SRFI 40
   ("A Library of Streams"
    (stream-null stream)
    (stream-cons (syntax (obj stream)))
    (stream? (lambda (obj)))
    (stream-null? (lambda (obj)))
    (stream-pair? (lambda (obj)))
    (stream-car (lambda (stream)))
    (stream-cdr (lambda (stream)))
    (stream-delay (syntax (expr)))
    (stream (lambda (obj \.\.\.)))
    (stream-unfoldn (lambda (generator-proc seed n)))
    (stream-map (lambda (proc stream \.\.\.)))
    (stream-for-each (lambda (proc stream \.\.\.) undefined))
    (stream-filter (lambda (pred stream)))
    )

   ()

   ;; SRFI 42
   ("Eager Comprehensions"
    (list-ec (syntax))
    (append-ec (syntax))
    (sum-ec (syntax))
    (min-ec (syntax))
    (max-ec (syntax))
    (any?-ec (syntax))
    (every?-ec (syntax))
    (first-ec (syntax))
    (do-ec (syntax))
    (fold-ec (syntax))
    (fold3-ec (syntax))
    (:list (syntax () undefined))
    (:string (syntax () undefined))
    (:vector (syntax () undefined))
    (:integers (syntax () undefined))
    (:range (syntax () undefined))
    (:real-range (syntax () undefined))
    (:char-range (syntax () undefined))
    (:port (syntax () undefined))
    (:do (syntax () undefined))
    (:let (syntax () undefined))
    (:parallel (syntax () undefined))
    (:while (syntax () undefined))
    (:until (syntax () undefined))
    )

   ;; SRFI 43
   ("Vector Library"
    (vector-unfold (f length initial-seed \.\.\.))
    (vector-unfold-right (lambda (f length initial-seed \.\.\.)))
    (vector-tabulate (lambda (f size)))
    (vector-copy (lambda (vec :optional start end fill)))
    (vector-reverse-copy (lambda (vec :optional start end)))
    (vector-append (lambda (vec \.\.\.)))
    (vector-concatenate (lambda (vector-list)))
    (vector-empty? (lambda (obj)))
    (vector= (lambda (eq-proc vec \.\.\.)))
    (vector-fold (lambda (kons knil vec \.\.\.)))
    (vector-fold-right (lambda (kons knil vec \.\.\.)))
    (vector-map (lambda (f vec \.\.\.)))
    (vector-map! (lambda (f vec \.\.\.)))
    (vector-for-each (lambda (f vec \.\.\.) undefined))
    (vector-count (lambda (pred vec \.\.\.)))
    (vector-index (lambda (pred vec \.\.\.)))
    (vector-index-right (lambda (pred vec \.\.\.)))
    (vector-skip (lambda (pred vec \.\.\.)))
    (vector-skip-right (lambda (pred vec \.\.\.)))
    (vector-binary-search (lambda (vec value cmp-proc)))
    (vector-any (lambda (pred vec \.\.\.)))
    (vector-every (lambda (pred vec \.\.\.)))
    (vector-swap! (lambda (vec i j) undefined))
    (vector-reverse! (lambda (vec :optional start end) undefined))
    (vector-copy! (lambda (target-vec t-start source-vec :optional start end) undefined))
    (vector-reverse-copy! (lambda (target-vec t-start source-vec :optional start end) undefined))
    (reverse-vector-to-list (lambda (vec :optional start end)))
    (reverse-list-to-vector (lambda (list)))
    )

   ;; SRFI 44
   ("Collections"
    )

   ;; SRFI 45
   ("Primitives for expressing iterative lazy algorithms"
    (delay (syntax (expr)))
    (lazy (syntax (expr)))
    (force (lambda (promise)))
    (eager (lambda (promise)))
    )

   ;; SRFI 46
   ("Basic Syntax-rules Extensions"
    (syntax-rules (syntax () undefined)))

   ;; SRFI 47
   ("Array"
    (make-array (lambda (prototype k \.\.\.)))
    (ac64 (lambda (:optional z)))
    (ac32 (lambda (:optional z)))
    (ar64 (lambda (:optional x1)))
    (ar32 (lambda (:optional x1)))
    (as64 (lambda (:optional n)))
    (as32 (lambda (:optional n)))
    (as16 (lambda (:optional n)))
    (as8 (lambda (:optional n)))
    (au64 (lambda (:optional n)))
    (au32 (lambda (:optional n)))
    (au16 (lambda (:optional n)))
    (au8 (lambda (:optional n)))
    (at1 (lambda (:optional bool)))
    (make-shared-array (lambda (array mapper k \.\.\.)))
    (array-rank (lambda (obj)))
    (array-dimensions (lambda (array)))
    (array-in-bounds? (lambda (array k \.\.\.)))
    (array-ref (lambda (array k \.\.\.)))
    (array-set! (lambda (array obj k \.\.\.)))
    )

   ;; SRFI 48
   ("Intermediate Format Strings"
    (format (lambda (port-or-boolean format-string arg \.\.\.))))

   ;; SRFI 49
   ("Indentation-sensitive syntax"
    )

   ()

   ;; SRFI 51
   ("Handling rest list"
    (rest-values (lambda (caller rest-list :optional args-number-limit default)))
    (arg-and (syntax))
    (arg-ands (syntax))
    (err-and (syntax))
    (err-ands (syntax))
    (arg-or (syntax))
    (arg-ors (syntax))
    (err-or (syntax))
    (err-ors (syntax))
    )

   ()

   ()

   ;; SRFI 54
   ("Formatting"
    (cat (lambda (obj \.\.\.))))

   ;; SRFI 55
   ("require-extension"
    (require-extension (syntax)))

   ()

   ;; SRFI 57
   ("Records"
    (define-record-type (syntax))
    (define-record-scheme (syntax))
    (record-update (syntax))
    (record-update! (syntax))
    (record-compose (syntax)))

   ;; SRFI 58
   ("Array Notation"
    )

   ;; SRFI 59
   ("Vicinity"
    (program-vicinity (lambda ()))
    (library-vicinity (lambda ()))
    (implementation-vicinity (lambda ()))
    (user-vicinity (lambda ()))
    (home-vicinity (lambda ()))
    (in-vicinity (lambda (vicinity filename)))
    (sub-vicinity (lambda (vicinity name)))
    (make-vicinity (lambda (dirname)))
    (path-vicinity (lambda (path)))
    (vicinity:suffix? (lambda (ch)))
    )

   ;; SRFI 60
   ("Integers as Bits"
    (bitwise-and (lambda (n \.\.\.) int))
    (bitwise-ior (lambda (n \.\.\.) int))
    (bitwise-xor (lambda (n \.\.\.) int))
    (bitwise-not (lambda (n) int))
    (bitwise-if (lambda (mask n m) int))
    (any-bits-set? (lambda (n m) bool))
    (bit-count (lambda (n) int))
    (integer-length (lambda (n) int))
    (first-bit-set (lambda (n) int))
    (bit-set? (lambda (i n) bool))
    (copy-bit (lambda (index n bool) int))
    (bit-field (lambda (n start end) int))
    (copy-bit-field (lambda (to-int from-int start end) int))
    (arithmetic-shift (lambda (n count) int))
    (rotate-bit-field (lambda (n count start end) int))
    (reverse-bit-field (lambda (n start end) int))
    (integer->list (lambda (k :optional len) list))
    (list->integer (lambda (list) int))
    )

   ;; SRFI 61
   ("A more general cond clause"
    (cond (syntax)))

   ;; SRFI 62
   ("S-expression comments"
    )

   ;; SRFI 63
   ("Homogeneous and Heterogeneous Arrays"
    )

   ;; SRFI 64
   ("A Scheme API for test suites"
    (test-assert (syntax))
    (test-eqv (syntax))
    (test-equal (syntax))
    (test-eq (syntax))
    (test-approximate (syntax))
    (test-error (syntax))
    (test-read-eval-string (lambda (string)))
    (test-begin (syntax (suite-name :optional count)))
    (test-end (syntax (suite-name)))
    (test-group (syntax (suite-name decl-or-expr \.\.\.)))
    (test-group-with-cleanup (syntax (suite-name decl-or-expr \.\.\.)))
    (test-match-name (lambda (name)))
    (test-match-nth (lambda (n :optional count)))
    (test-match-any (lambda (specifier \.\.\.)))
    (test-match-all (lambda (specifier \.\.\.)))
    (test-skip (syntax (specifier)))
    (test-expect-fail (syntax (specifier)))
    (test-runner? (lambda (obj)))
    (test-runner-current (lambda (:optional runner)))
    (test-runner-get (lambda ()))
    (test-runner-simple (lambda ()))
    (test-runner-null (lambda ()))
    (test-runner-create (lambda ()))
    (test-runner-factory (lambda (:optional factory)))
    (test-apply (syntax (runner specifier \.\.\.)))
    (test-with-runner (syntax (runner decl-or-expr \.\.\.)))
    (test-result-kind (lambda (:optional runner)))
    (test-passed? (lambda (:optional runner)))
    (test-result-ref (lambda (runner prop-name (:optional default))))
    (test-result-set! (lambda (runner prop-name value)))
    (test-result-remove (lambda (runner prop-name)))
    (test-result-clear (lambda (runner)))
    (test-result-alist (lambda (runner)))
    (test-runner-on-test-begin (lambda (runner :optional proc)))
    (test-runner-on-test-begin! (lambda (runner :optional proc)))
    (test-runner-on-test-end (lambda (runner :optional proc)))
    (test-runner-on-test-end! (lambda (runner :optional proc)))
    (test-runner-on-group-begin (lambda (runner :optional proc)))
    (test-runner-on-group-begin! (lambda (runner :optional proc)))
    (test-runner-on-group-end (lambda (runner :optional proc)))
    (test-runner-on-group-end! (lambda (runner :optional proc)))
    (test-runner-on-bad-count (lambda (runner :optional proc)))
    (test-runner-on-bad-count! (lambda (runner :optional proc)))
    (test-runner-on-bad-end-name (lambda (runner :optional proc)))
    (test-runner-on-bad-end-name! (lambda (runner :optional proc)))
    (test-runner-on-final (lambda (runner :optional proc)))
    (test-runner-on-final! (lambda (runner :optional proc)))
    (test-runner-pass-count (lambda (runner)))
    (test-runner-fail-count (lambda (runner)))
    (test-runner-xpass-count (lambda (runner)))
    (test-runner-skip-count (lambda (runner)))
    (test-runner-test-name (lambda (runner)))
    (test-runner-group-path (lambda (runner)))
    (test-runner-group-stack (lambda (runner)))
    (test-runner-aux-value (lambda (runner)))
    (test-runner-aux-value! (lambda (runner)))
    (test-runner-reset (lambda (runner)))
    )

   ()

   ;; SRFI 66
   ("Octet Vectors"
    (make-u8vector (lambda (len n)))
    (u8vector (lambda (n \.\.\.)))
    (u8vector->list (lambda (u8vector)))
    (list->u8vector (lambda (octet-list)))
    (u8vector-length u8vector)
    (u8vector-ref (lambda (u8vector k)))
    (u8vector-set! (lambda (u8vector k n)))
    (u8vector=? (lambda (u8vector-1 u8vector-2)))
    (u8vector-compare (lambda (u8vector-1 u8vector-2)))
    (u8vector-copy! (lambda (source source-start target target-start n)))
    (u8vector-copy (lambda (u8vector)))
    )

   ;; SRFI 67
   ("Compare Procedures"
    )

   ()

   ;; SRFI 69
   ("Basic hash tables"
    )

   ;; SRFI 70
   ("Numbers"
    )

   ;; SRFI 71
   ("LET-syntax for multiple values"
    )

   ;; SRFI 72
   ("Simple hygienic macros"
    )

   ()

   ;; SRFI 74
   ("Octet-Addressed Binary Blocks"
    )

   ])

(defvar *scheme-chicken-modules*
  '((extras
     (->string (lambda (obj) str))
     (alist->hash-table (lambda (alist) hash-table))
     (alist-ref (lambda (alist key :optional eq-fn default)))
     (alist-update! (lambda (key value alist :optional eq-fn) undefined))
     (atom? (lambda (obj) bool))
     (binary-search (lambda (vec proc)))
     (butlast (lambda (list) list) "drops the last element of list")
     (call-with-input-string (lambda (string proc)))
     (call-with-output-string (lambda (proc) str))
     (chop (lambda (list k) list))
     (complement (lambda (f) f2))
     (compose (lambda (f1 f2 \.\.\.) f))
     (compress (lambda (boolean-list list)))
     (conc (lambda (obj \.\.\.)))
     (conjoin (lambda (pred \.\.\.) pred))
     (constantly (lambda (obj \.\.\.) f))
     (disjoin (lambda (pred \.\.\.) pred))
     (each (lambda (proc \.\.\.) proc))
     (flatten (lambda (list1 \.\.\.) list))
     (flip (lambda (proc) proc))
     (format (lambda (format-string arg \.\.\.)))
     (fprintf (lambda (port format-string arg \.\.\.)))
     (hash (lambda (obj :optional n) int))
     (hash-by-identity (lambda (obj :optional n) int))
     (hash-table->alist (lambda (hash-table) alist))
     (hash-table-copy (lambda (hash-table) hash-table))
     (hash-table-delete! (lambda (hash-table key) undefined))
     (hash-table-equivalence-function (lambda (hash-table) pred))
     (hash-table-exists? (lambda (hash-table key) bool))
     (hash-table-fold (lambda (hash-table f init-value)))
     (hash-table-hash-function (lambda (hash-table) f))
     (hash-table-keys (lambda (hash-table) list))
     (hash-table-merge! (lambda (hash-table1 hash-table2) undefined))
     (hash-table-ref (lambda (hash-table key :optional thunk)))
     (hash-table-ref/default (lambda (hash-table key default)))
     (hash-table-remove! (lambda (hash-table proc) undefined))
     (hash-table-set! (lambda (hash-table key value) undefined))
     (hash-table-size (lambda (hash-table) n))
     (hash-table-update! (lambda (hash-table key proc :optional thunk) undefined))
     (hash-table-update!/default (lambda (hash-table key proc default) undefined))
     (hash-table-values (lambda (hash-table) list))
     (hash-table-walk (lambda (hash-table proc) undefined))
     (hash-table? (lambda (obj) bool))
     (identity (lambda (obj)))
     (intersperse (lambda (list obj) list))
     (join (lambda (list-of-lists :optional list) list))
     (list->queue (lambda (list) queue))
     (list-of (lambda (pred)))
     (make-hash-table (lambda (:optional eq-fn hash-fn size) hash-table))
     (make-input-port (lambda (read-proc ready?-pred close-proc :optional peek-proc) input-port))
     (make-output-port (lambda (write-proc close-proc :optional flush-proc) output-port))
     (make-queue (lambda () queue))
     (merge (lambda (list1 list2 less-fn) list))
     (merge! (lambda (list1 list2 less-fn) list))
     (noop (lambda (obj \.\.\.) undefined))
     (pp (lambda (obj :optional output-port) undefined))
     (pretty-print (lambda (obj :optional output-port) undefined))
     (pretty-print-width (lambda (:optional new-width) n))
     (printf (lambda (format-string arg \.\.\.) undefined))
     (project (lambda (n) proc))
     (queue->list (lambda (queue) list))
     (queue-add! (lambda (queue obj) undefined))
     (queue-empty? (lambda (queue) bool))
     (queue-first (lambda (queue)))
     (queue-last (lambda (queue)))
     (queue-push-back! (lambda (queue obj) undefined))
     (queue-push-back-list! (lambda (queue list) undefined))
     (queue-remove! (lambda (queue) undefined))
     (queue? (lambda (obj) bool))
     (random (lambda (n) n))
     (randomize (lambda (:optional x1) undefined))
     (rassoc (lambda (key list :optional eq-fn)))
     (read-file (lambda (:optional file-or-port reader-fn max-count) str))
     (read-line (lambda (:optional port limit) str))
     (read-lines (lambda (:optional port max) list))
     (read-string (lambda (:optional n port) str))
     (read-string! (lambda (n dest :optional port start) undefined))
     (read-token (lambda (predicate :optional port) str))
     (shuffle (lambda (list) list))
     (sort (lambda (sequence less-fn) sequence))
     (sort! (lambda (sequence less-fn) sequence))
     (sorted? (lambda (sequence less-fn) bool))
     (sprintf (lambda (format-string arg \.\.\.) str))
     (string-chomp (lambda (str :optional suffix-str) str))
     (string-chop (lambda (str length) list))
     (string-ci-hash (lambda (str :optional n) n))
     (string-compare3 (lambda (str1 str2) n))
     (string-compare3-ci (lambda (str1 str2) n))
     (string-hash (lambda (str1 :optional n) n))
     (string-intersperse (lambda (list :optional seperator-string) str))
     (string-split (lambda (str :optional delimiter-str keep-empty?) list))
     (string-translate (lambda (str from-str :optional to-str) str))
     (string-translate* (lambda (str list) str))
     (substring-ci=? (lambda (str1 str2 :optional start1 start2 length) str))
     (substring-index (lambda (which-str where-str :optional start) i))
     (substring-index-ci (lambda (which-str where-str :optional start) i))
     (substring=? (lambda (str1 str2 :optional start1 start2 length) bool))
     (tail? (lambda (obj list) bool))
     (with-error-output-to-port (lambda (output-port thunk)))
     (with-input-from-port (lambda (port thunk)))
     (with-input-from-string (lambda (str thunk)))
     (with-output-to-port (lambda (port thunk)))
     (with-output-to-string (lambda (thunk) str))
     (write-line (lambda (str :optional port) undefined))
     (write-string (lambda (str :optional num port) undefined))
     )
    (lolevel
     (address->pointer (lambda (n) ptr))
     (align-to-word (lambda (ptr-or-int) ptr))
     (allocate (lambda (size) block))
     (block-ref (lambda (block index) int))
     (block-set! (lambda (block index obj) undefined))
     (byte-vector (lambda (n \.\.\.) byte-vector))
     (byte-vector->list (lambda (byte-vector) list))
     (byte-vector->string (lambda (byte-vector) string))
     (byte-vector-fill! (lambda (byte-vector n) undefined))
     (byte-vector-length (lambda (byte-vector) n))
     (byte-vector-ref (lambda (byte-vector i) int))
     (byte-vector-set! (lambda (byte-vector i n) undefined))
     (byte-vector? (lambda (obj) bool))
     (extend-procedure (lambda (proc x1) proc))
     (extended-procedure? (lambda (proc) bool))
     (free (lambda (pointer) undefined))
     (global-bound? (lambda (sym) bool))
     (global-make-unbound! (lambda (sym) undefined))
     (global-ref (lambda (sym)))
     (global-set! (lambda (sym val) undefined))
     (list->byte-vector (lambda (list) byte-vector))
     (locative->object (lambda (locative) obj))
     (locative-ref (lambda (locative)))
     (locative-set! (lambda (locative val) undefined))
     (locative? (lambda (obj) bool))
     (make-byte-vector (lambda (size :optional init-n) byte-vector))
     (make-locative (lambda (obj :optional index) locative))
     (make-record-instance (lambda (sym arg \.\.\.)))
     (make-static-byte-vector (lambda (size :optional init-n)))
     (make-weak-locative (lambda (obj :optional index) locative))
     (move-memory! (lambda (from to :optional bytes from-offset to-offset) undefined))
     (mutate-procedure (lambda (proc proc) proc))
     (null-pointer (lambda () pointer))
     (null-pointer? (lambda (pointer) bool))
     (number-of-bytes (lambda (block) int))
     (number-of-slots (lambda (block) int))
     (object->pointer (lambda (obj) ptr))
     (object-become! (lambda (alist) undefined))
     (object-copy (lambda (obj)))
     (object-evict (lambda (obj :optional allocator-proc)))
     (object-evict-to-location (lambda (obj ptr :optional limit)))
     (object-evicted? (lambda (obj) bool))
     (object-release (lambda (obj :optional releaser-proc)))
     (object-size (lambda (obj) int))
     (object-unevict (lambda (obj :optional full)))
     (pointer->address (lambda (ptr) n))
     (pointer->object (lambda (ptr)))
     (pointer-f32-ref (lambda (ptr) real))
     (pointer-f32-set! (lambda (ptr x1) undefined))
     (pointer-f64-ref (lambda (ptr) real))
     (pointer-f64-set! (lambda (ptr x1) undefined))
     (pointer-offset (lambda (ptr n) n))
     (pointer-s16-ref (lambda (ptr) int))
     (pointer-s16-set! (lambda (ptr n) undefined))
     (pointer-s32-ref (lambda (ptr) int))
     (pointer-s32-set! (lambda (ptr n) undefined))
     (pointer-s8-ref (lambda (ptr) int))
     (pointer-s8-set! (lambda (ptr n) undefined))
     (pointer-tag (lambda (ptr) tag))
     (pointer-u16-ref (lambda (ptr) int))
     (pointer-u16-set! (lambda (ptr n) undefined))
     (pointer-u32-ref (lambda (ptr) int))
     (pointer-u32-set! (lambda (ptr n) undefined))
     (pointer-u8-ref (lambda (ptr) int))
     (pointer-u8-set! (lambda (ptr n) undefined))
     (pointer=? (lambda (ptr1 ptr2) bool))
     (pointer? (lambda (obj) bool))
     (procedure-data (lambda (proc)))
     (record->vector (lambda (block) vector))
     (record-instance? (lambda (obj) bool))
     (set-invalid-procedure-call-handler! (lambda (proc) undefined))
     (set-procedure-data! (lambda (proc obj) undefined))
     (static-byte-vector->pointer (lambda (byte-vector) pointer))
     (string->byte-vector (lambda (str) byte-vector))
     (tag-pointer (lambda (ptr tag)))
     (tagged-pointer? (lambda (obj tag) bool))
     (unbound-variable-value (lambda (:optional value)))
     )
    (posix
     (_exit (lambda (:optional n) undefined))
     (call-with-input-pipe (lambda (cmdline-string proc :optional mode)))
     (call-with-output-pipe (lambda (cmdline-string proc :optional mode)))
     (change-directory (lambda (dir)))
     (change-file-mode (lambda (filename mode)))
     (change-file-owner (lambda (filename user-n group-n)))
     (close-input-pipe (lambda (input-port)))
     (close-output-pipe (lambda (output-port)))
     (create-directory (lambda (filename)))
     (create-fifo (lambda (filename :optional mode)))
     (create-pipe (lambda ()))
     (create-session (lambda ()))
     (create-symbolic-link (lambda (old-filename new-filename)))
     (current-directory (lambda (:optional new-dir)))
     (current-effective-group-id (lambda () int))
     (current-effective-user-id (lambda () int))
     (current-environment (lambda ()))
     (current-group-id (lambda ()))
     (current-process-id (lambda ()))
     (current-user-id (lambda ()))
     (delete-directory (lambda (dir)))
     (directory (lambda (:optional dir show-dotfiles?) list))
     (directory? (lambda (filename) bool))
     (duplicate-fileno (lambda (old-n :optional new-n)))
;;      (errno/acces integer)
;;      (errno/again integer)
;;      (errno/badf integer)
;;      (errno/busy integer)
;;      (errno/child integer)
;;      (errno/exist integer)
;;      (errno/fault integer)
;;      (errno/intr integer)
;;      (errno/inval integer)
;;      (errno/io integer)
;;      (errno/isdir integer)
;;      (errno/mfile integer)
;;      (errno/noent integer)
;;      (errno/noexec integer)
;;      (errno/nomem integer)
;;      (errno/nospc integer)
;;      (errno/notdir integer)
;;      (errno/perm integer)
;;      (errno/pipe integer)
;;      (errno/rofs integer)
;;      (errno/spipe integer)
;;      (errno/srch integer)
;;      (errno/wouldblock integer)
     (fifo? (lambda (filename) bool))
     (file-access-time (lambda (filename) real))
     (file-change-time (lambda (filename) real))
     (file-close (lambda (fileno)))
     (file-execute-access? (lambda (filename) bool))
     (file-link (lambda (old-filename new-filename)))
     (file-lock (lambda (port :optional start len)))
     (file-lock/blocking (lambda (port :optional start len)))
     (file-mkstemp (lambda (template-filename)))
     (file-modification-time (lambda (filename) real))
     (file-open (lambda (filename (flags open-mode open/binary open/excl open/fsync open/noctty open/nonblock open/rdonly open/rdwr open/read open/sync open/text) :optional mode) fileno))
     (file-owner (lambda (filename)))
     (file-permissions (lambda (filename) int))
     (file-position (lambda (port-or-fileno) int))
     (file-read (lambda (fileno size :optional buffer-string)))
     (file-read-access? (lambda (filename) bool))
     (file-select (lambda (read-fd-list write-fd-list :optional timeout)))
     (file-size (lambda (filename) int))
     (file-stat (lambda (filename :optional follow-link?)))
     (file-test-lock (lambda (port :optional start len)))
     (file-truncate (lambda (filename-or-fileno offset)))
     (file-unlock (lambda (lock)))
     (file-write (lambda (fileno buffer-string :optional size)))
     (file-write-access? (lambda (filename)))
     (fileno/stderr integer)
     (fileno/stdin integer)
     (fileno/stdout integer)
     (find-files (lambda (dir pred :optional action-proc identity limit)))
     (get-groups (lambda ()))
     (get-host-name (lambda ()))
     (glob (lambda (pattern1 \.\.\.)))
     (group-information (lambda (group-name-or-n)))
     (initialize-groups (lambda (user-name base-group-n)))
     (local-time->seconds (lambda (vector)))
     (local-timezone-abbreviation (lambda ()))
     (map-file-to-memory (lambda (address len protection flag fileno :optional offset)))
     (memory-mapped-file-pointer (lambda (mmap)))
     (memory-mapped-file? (lambda (obj)))
     (open-input-file* (lambda (fileno :optional (flags open-mode open/binary open/excl open/fsync open/noctty open/nonblock open/rdonly open/rdwr open/read open/sync open/text))))
     (open-input-pipe (lambda (cmdline-string :optional mode)))
     (open-output-file* (lambda (fileno :optional (flags open-mode open/append open/binary open/creat open/excl open/fsync open/noctty open/nonblock open/rdwr open/sync open/text open/trunc open/write open/wronly))))
     (open-output-pipe (lambda (cmdline-string :optional mode)))
;;      (open/append integer)
;;      (open/binary integer)
;;      (open/creat integer)
;;      (open/excl integer)
;;      (open/fsync integer)
;;      (open/noctty integer)
;;      (open/nonblock integer)
;;      (open/rdonly integer)
;;      (open/rdwr integer)
;;      (open/read integer)
;;      (open/sync integer)
;;      (open/text integer)
;;      (open/trunc integer)
;;      (open/write integer)
;;      (open/wronly integer)
     (parent-process-id (lambda ()))
;;      (perm/irgrp integer)
;;      (perm/iroth integer)
;;      (perm/irusr integer)
;;      (perm/irwxg integer)
;;      (perm/irwxo integer)
;;      (perm/irwxu integer)
;;      (perm/isgid integer)
;;      (perm/isuid integer)
;;      (perm/isvtx integer)
;;      (perm/iwgrp integer)
;;      (perm/iwoth integer)
;;      (perm/iwusr integer)
;;      (perm/ixgrp integer)
;;      (perm/ixoth integer)
;;      (perm/ixusr integer)
;;      (pipe/buf integer)
     (port->fileno (lambda (port)))
     (process (lambda (cmdline-string :optional arg-list env-list)))
     (process-execute (lambda (filename :optional arg-list env-list)))
     (process-fork (lambda (:optional thunk)))
     (process-group-id (lambda ()))
     (process-run (lambda (filename :optional list)))
     (process-signal (lambda (pid :optional signal)))
     (process-wait (lambda (:optional pid nohang?)))
     (read-symbolic-link (lambda (filename) filename))
     (regular-file? (lambda (filename)))
     (seconds->local-time (lambda (seconds)))
     (seconds->string (lambda (seconds)))
     (seconds->utc-time (lambda (seconds)))
     (set-alarm! (lambda (seconds)))
     (set-buffering-mode! (lambda (port mode :optional buf-size)))
     (set-file-position! (lambda (port-or-fileno pos :optional whence)))
     (set-group-id! (lambda (n)))
     (set-groups! (lambda (group-n-list)))
     (set-process-group-id! (lambda (process-n n)))
     (set-root-directory! (lambda (dir)) "chroot")
     (set-signal-handler! (lambda (sig-n proc)))
     (set-signal-mask! (lambda (sig-n-list)))
     (set-user-id! (lambda (n)))
     (setenv (lambda (name value-string)))
;;      (signal/abrt integer)
;;      (signal/alrm integer)
;;      (signal/chld integer)
;;      (signal/cont integer)
;;      (signal/fpe integer)
;;      (signal/hup integer)
;;      (signal/ill integer)
;;      (signal/int integer)
;;      (signal/io integer)
;;      (signal/kill integer)
;;      (signal/pipe integer)
;;      (signal/prof integer)
;;      (signal/quit integer)
;;      (signal/segv integer)
;;      (signal/stop integer)
;;      (signal/term integer)
;;      (signal/trap integer)
;;      (signal/tstp integer)
;;      (signal/urg integer)
;;      (signal/usr1 integer)
;;      (signal/usr2 integer)
;;      (signal/vtalrm integer)
;;      (signal/winch integer)
;;      (signal/xcpu integer)
;;      (signal/xfsz integer)
     (sleep (lambda (seconds)))
     (symbolic-link? (lambda (filename)))
     (system-information (lambda ()))
     (terminal-name (lambda (port)))
     (terminal-port? (lambda (port)))
     (time->string (lambda (vector)))
     (unmap-file-from-memory (lambda (mmap :optional len)))
     (unsetenv (lambda (name) undefined))
     (user-information (lambda ((or integer (string scheme-complete-user-name))) list))
     (utc-time->seconds (lambda (vector)))
     (with-input-from-pipe (lambda (cmdline-string thunk :optional mode)))
     (with-output-to-pipe (lambda (cmdline-string thunk :optional mode)))
     )
    (regex
     (glob->regexp (lambda (pattern)))
     (glob? (lambda (obj)))
     (grep (lambda (pattern list) list))
     (regexp (lambda (pattern ignore-case? ignore-space? utf-8?)))
     (regexp-escape (lambda (str) str))
     (regexp? (lambda (obj) bool))
     (string-match (lambda (pattern str :optional start)))
     (string-match-positions (lambda (pattern str :optional start)))
     (string-search (lambda (pattern str :optional start)))
     (string-search-positions (lambda (pattern str :optional start)))
     (string-split-fields (lambda (pattern str :optional mode start)))
     (string-substitute (lambda (pattern subst str :optional mode)))
     (string-substitute* (lambda (str subst-list :optional mode)))
     )
    (tcp
     (tcp-abandon-port (lambda (port)))
     (tcp-accept (lambda (listener)))
     (tcp-accept-ready? (lambda (listener)))
     (tcp-addresses (lambda (port)))
     (tcp-buffer-size (lambda (:optional new-size)))
     (tcp-close (lambda (listener)))
     (tcp-connect (lambda ((string scheme-complete-host-name) :optional (string scheme-complete-port-name))))
     (tcp-listen (lambda (tcp-port-n :optional backlog-n host-string)))
     (tcp-listener-fileno (lambda (listener)))
     (tcp-listener-port (lambda (listener)))
     (tcp-listener? (lambda (obj)))
     (tcp-port-numbers (lambda (port)))
     )
    (utils
     (absolute-pathname? (lambda (pathname)))
     (create-temporary-file (lambda (:optional ext-str)))
     (decompose-pathname (lambda (pathname)))
     (delete-file* (lambda (filename)))
     (for-each-argv-line (lambda (proc) undefined))
     (for-each-line (lambda (proc :optional input-port) undefined))
     (make-absolute-pathname (lambda (dir filename :optional ext-str)))
     (make-pathname (lambda (dir filename :optional ext-str)))
     (pathname-directory (lambda (pathname)))
     (pathname-extension (lambda (pathname)))
     (pathname-file (lambda (pathname)))
     (pathname-replace-directory (lambda (pathname dir)))
     (pathname-replace-extension (lambda (pathname ext-str)))
     (pathname-replace-file (lambda (pathname filename)))
     (pathname-strip-directory (lambda (pathname)))
     (pathname-strip-extension (lambda (pathname)))
     (port-for-each (lambda (read-fn thunk) undefined))
     (port-map (lambda (read-fn thunk)))
     (read-all (lambda (:optional file-or-port)))
     (shift! (lambda (list :optional default)))
     (system* (lambda (format-string arg1 \.\.\.)))
     (unshift! (lambda (obj pair)))
     )
    ))

;; another big table - consider moving to a separate file
(defvar *scheme-implementation-exports*
  '((chicken
     (abort (lambda (obj) undefined))
     (add1 (lambda (z) z))
     (andmap (lambda (pred list) bool))
     (any? (lambda (obj) bool))
     (argc+argv (lambda () (values n ptr)))
     (argv (lambda () list))
     (bit-set? (lambda (n index) bool))
     (bitwise-and (lambda (n \.\.\.) n))
     (bitwise-ior (lambda (n \.\.\.) n))
     (bitwise-not (lambda (n \.\.\.) n))
     (bitwise-xor (lambda (n \.\.\.) n))
     (blob->string (lambda (blob) string))
     (blob-size (lambda (blob) n))
     (blob? (lambda (obj) bool))
     (breakpoint (lambda (:optional name)))
     (build-platform (lambda () symbol))
     (c-runtime (lambda () symbol))
     (call/cc (lambda (proc)))
     (case-sensitive (lambda (:optional on?)))
     (chicken-home (lambda () string))
     (chicken-version (lambda () string))
     (command-line-arguments (lambda () list))
     (condition-predicate (lambda (kind) pred))
     (condition-property-accessor (lambda (kind prop :optional err?) proc))
     (condition? (lambda (obj) bool))
     (continuation-capture (lambda (proc)))
     (continuation-graft (lambda (continuation thunk)))
     (continuation-return (lambda (continuation vals\.\.\.)))
     (continuation? (lambda (obj) bool))
     (copy-read-table (lambda (read-table) read-table))
     (cpu-time (lambda () (values n n)))
     (current-error-port (lambda () output-port))
     (current-exception-handler (lambda () proc))
     (current-gc-milliseconds (lambda () n))
     (current-milliseconds (lambda () n))
     (current-read-table (lambda () read-table))
     (current-seconds (lambda () x1))
     (define-reader-ctor (lambda (sym proc) undefined))
     (delete-file (lambda (filename) undefined))
     (disable-interrupts (lambda () undefined))
     (dynamic-load-libraries (lambda () list))
     (dynamic-wind (lambda (before-thunk thunk after-thunk)))
     (enable-interrupts (lambda () undefined))
     (enable-warnings (lambda () undefined))
     (errno (lambda () n))
     (error (lambda (error-string args \.\.\.) undefined))
     (eval-handler (lambda () proc))
     (exit (lambda (:optional n) undefined))
     (exit-handler (lambda () proc))
     (extension-info (lambda (proc)))
     (extension-information (lambda (proc)))
     (feature? (lambda (sym) bool))
     (features (lambda () list))
     (file-exists? (lambda (filename) bool))
     (finite? (lambda (z) bool))
     (fixnum? (lambda (obj) bool))
     (flonum? (lambda (obj) bool))
     (flush-output (lambda (:optional port) undefined))
     (force (lambda (promise)))
     (force-finalizers (lambda (f args \.\.\.)))
     (fp* (lambda (x1 x2) x3))
     (fp+ (lambda (x1 x2) x3))
     (fp- (lambda (x1 x2) x3))
     (fp/ (lambda (x1 x2) x3))
     (fp< (lambda (x1 x2) x3))
     (fp<= (lambda (x1 x2) x3))
     (fp= (lambda (x1 x2) x3))
     (fp> (lambda (x1 x2) x3))
     (fp>= (lambda (x1 x2) x3))
     (fpmax (lambda (x1 x2) x3))
     (fpmin (lambda (x1 x2) x3))
     (fpneg (lambda (x1 x2) x3))
     (fx* (lambda (n1 n2) n))
     (fx+ (lambda (n1 n2) n))
     (fx- (lambda (n1 n2) n))
     (fx/ (lambda (n1 n2) n))
     (fx< (lambda (n1 n2) n))
     (fx<= (lambda (n1 n2) n))
     (fx= (lambda (n1 n2) n))
     (fx> (lambda (n1 n2) n))
     (fx>= (lambda (n1 n2) n))
     (fxand (lambda (n1 n2) n))
     (fxior (lambda (n1 n2) n))
     (fxmax (lambda (n1 n2) n))
     (fxmin (lambda (n1 n2) n))
     (fxmod (lambda (n1 n2) n))
     (fxneg (lambda (n1 n2) n))
     (fxnot (lambda (n1 n2) n))
     (fxshl (lambda (n1 n2) n))
     (fxshr (lambda (n1 n2) n))
     (fxxor (lambda (n1 n2) n))
     (gc (lambda () n))
     (gensym (lambda (:optional name) sym))
     (get-call-chain (lambda (:optional n) list))
     (get-keyword (lambda (sym list :optional default)))
     (get-line-number (lambda (sexp) n))
     (get-output-string (lambda (string-output-port) string))
     (getenv (lambda (name) string))
     (getter-with-setter (lambda (get-proc set-proc) proc))
     (implicit-exit-handler (lambda (:optional proc) proc))
     (invalid-procedure-call-handler (lambda (:optional proc) proc))
     (keyword->string (lambda (sym) string))
     (keyword-style (lambda (:optional sym) sym))
     (keyword? (lambda (obj) bool))
     (load-library (lambda (sym) undefined))
     (load-noisily (lambda (string) undefined))
     (load-relative (lambda (string) undefined))
     (load-verbose (lambda (:optional bool) bool))
     (machine-byte-order (lambda () sym))
     (machine-type (lambda () sym))
     (macro? (lambda (obj) bool))
     (macroexpand (lambda (sexp) sexp))
     (macroexpand-1 (lambda (sexp) sexp))
     (make-blob (lambda (size) blob))
     (make-composite-condition (lambda (condition \.\.\.) condition))
     (make-parameter (lambda (val) proc))
     (make-property-condition (lambda (kind \.\.\.) condition))
     (match-error-control (lambda (:optional proc) proc))
     (match-error-procedure (lambda (:optional proc) proc))
     (memory-statistics (lambda () vector))
     (on-exit (lambda (thunk) undefined))
     (open-input-string (lambda (string) string-input-port))
     (open-output-string (lambda () string-output-port))
     (ormap (lambda (pred list \.\.\.) bool))
     (port-name (lambda (port) name))
     (port-position (lambda (port) n))
     (port? (lambda (obj) bool))
     (print (lambda (obj \.\.\.) undefined))
     (print* (lambda (obj \.\.\.) undefined))
     (print-backtrace (lambda (:optional n) undefined))
     (print-call-chain (lambda (:optional n) undefined))
     (print-error-message (lambda (err args \.\.\.) undefined))
     (procedure-information (lambda (proc)))
     (program-name (lambda (:optional name) name))
     (provide (lambda (name)))
     (provided? (lambda (name) bool))
     (rational? (lambda (obj) bool))
     (read-byte (lambda (:optional input-port) n))
     (register-feature! (lambda (name) undefined))
     (rename-file (lambda (old-name new-name) undefined))
     (repl (lambda () undefined))
     (repository-path (lambda (:optional dirname) dirname))
     (require (lambda (sym \.\.\.) undefined))
     (reset (lambda () undefined))
     (reset-handler (lambda (:optional proc) proc))
     (return-to-host (lambda () undefined))
     (reverse-list->string (lambda (list) string))
     (set-dynamic-load-mode! (lambda (obj) undefined))
     (set-extension-specifier! (lambda (name proc) undefined))
     (set-finalizer! (lambda (obj proc) undefined))
     (set-gc-report! (lambda (bool) undefined))
     (set-parameterized-read-syntax! (lambda (ch proc) undefined))
     (set-port-name! (lambda (port name) undefined))
     (set-read-syntax! (lambda (ch proc) undefined))
     (set-sharp-read-syntax! (lambda (ch proc) undefined))
     (setter (lambda (proc) proc))
     (signal (lambda (n) undefined))
     (signum (lambda (x1) x2))
     (singlestep (lambda (thunk)))
     (software-type (lambda () sym))
     (software-version (lambda () sym))
     (string->blob (lambda (string) blob))
     (string->keyword (lambda (string) sym))
     (string->uninterned-symbol (lambda (string) sym))
     (string-copy (lambda (string) string))
     (sub1 (lambda (z1) z2))
     (syntax-error (lambda (args \.\.\.) undefined))
     (system (lambda (str) n))
     (test-feature? (lambda (obj) bool))
     (undefine-macro! (lambda (sym) undefined))
     (unregister-feature! (lambda (sym) undefined))
     (use (special symbol scheme-chicken-available-modules)
          "import extensions into top-level namespace")
     (vector-copy! (lambda (from-vector to-vector :optional start) undefined))
     (vector-resize (lambda (vec n :optional init)))
     (void (lambda () undefined))
     (warning (lambda (msg-str args \.\.\.) undefined))
     (with-exception-handler (lambda (handler thunk)))
     (write-byte (lambda (n :optional output-port) undefined))
     )
    (gauche
     (E2BIG integer)
     (EACCES integer)
     (EADDRINUSE integer)
     (EADDRNOTAVAIL integer)
     (EADV integer)
     (EAFNOSUPPORT integer)
     (EAGAIN integer)
     (EALREADY integer)
     (EBADE integer)
     (EBADF integer)
     (EBADFD integer)
     (EBADMSG integer)
     (EBADR integer)
     (EBADRQC integer)
     (EBADSLT integer)
     (EBFONT integer)
     (EBUSY integer)
     (ECANCELED integer)
     (ECHILD integer)
     (ECHRNG integer)
     (ECOMM integer)
     (ECONNABORTED integer)
     (ECONNREFUSED integer)
     (ECONNRESET integer)
     (EDEADLK integer)
     (EDEADLOCK integer)
     (EDESTADDRREQ integer)
     (EDOM integer)
     (EDOTDOT integer)
     (EDQUOT integer)
     (EEXIST integer)
     (EFAULT integer)
     (EFBIG integer)
     (EHOSTDOWN integer)
     (EHOSTUNREACH integer)
     (EIDRM integer)
     (EILSEQ integer)
     (EINPROGRESS integer)
     (EINTR integer)
     (EINVAL integer)
     (EIO integer)
     (EISCONN integer)
     (EISDIR integer)
     (EISNAM integer)
     (EKEYEXPIRED integer)
     (EKEYREJECTED integer)
     (EKEYREVOKED integer)
     (EL2HLT integer)
     (EL2NSYNC integer)
     (EL3HLT integer)
     (EL3RST integer)
     (ELIBACC integer)
     (ELIBBAD integer)
     (ELIBEXEC integer)
     (ELIBMAX integer)
     (ELIBSCN integer)
     (ELNRNG integer)
     (ELOOP integer)
     (EMEDIUMTYPE integer)
     (EMFILE integer)
     (EMLINK integer)
     (EMSGSIZE integer)
     (EMULTIHOP integer)
     (ENAMETOOLONG integer)
     (ENAVAIL integer)
     (ENETDOWN integer)
     (ENETRESET integer)
     (ENETUNREACH integer)
     (ENFILE integer)
     (ENOANO integer)
     (ENOBUFS integer)
     (ENOCSI integer)
     (ENODATA integer)
     (ENODEV integer)
     (ENOENT integer)
     (ENOEXEC integer)
     (ENOKEY integer)
     (ENOLCK integer)
     (ENOLINK integer)
     (ENOMEDIUM integer)
     (ENOMEM integer)
     (ENOMSG integer)
     (ENONET integer)
     (ENOPKG integer)
     (ENOPROTOOPT integer)
     (ENOSPC integer)
     (ENOSR integer)
     (ENOSTR integer)
     (ENOSYS integer)
     (ENOTBLK integer)
     (ENOTCONN integer)
     (ENOTDIR integer)
     (ENOTEMPTY integer)
     (ENOTNAM integer)
     (ENOTSOCK integer)
     (ENOTTY integer)
     (ENOTUNIQ integer)
     (ENXIO integer)
     (EOPNOTSUPP integer)
     (EOVERFLOW integer)
     (EPERM integer)
     (EPFNOSUPPORT integer)
     (EPIPE integer)
     (EPROTO integer)
     (EPROTONOSUPPORT integer)
     (EPROTOTYPE integer)
     (ERANGE integer)
     (EREMCHG integer)
     (EREMOTE integer)
     (EREMOTEIO integer)
     (ERESTART integer)
     (EROFS integer)
     (ESHUTDOWN integer)
     (ESOCKTNOSUPPORT integer)
     (ESPIPE integer)
     (ESRCH integer)
     (ESRMNT integer)
     (ESTALE integer)
     (ESTRPIPE integer)
     (ETIME integer)
     (ETIMEDOUT integer)
     (ETOOMANYREFS integer)
     (ETXTBSY integer)
     (EUCLEAN integer)
     (EUNATCH integer)
     (EUSERS integer)
     (EWOULDBLOCK integer)
     (EXDEV integer)
     (EXFULL integer)
     (F_OK integer)
     (LC_ALL integer)
     (LC_COLLATE integer)
     (LC_CTYPE integer)
     (LC_MONETARY integer)
     (LC_NUMERIC integer)
     (LC_TIME integer)
     (RAND_MAX integer)
     (R_OK integer)
     (SEEK_CUR integer)
     (SEEK_END integer)
     (SEEK_SET integer)
     (SIGABRT integer)
     (SIGALRM integer)
     (SIGBUS integer)
     (SIGCHLD integer)
     (SIGCONT integer)
     (SIGFPE integer)
     (SIGHUP integer)
     (SIGILL integer)
     (SIGINT integer)
     (SIGIO integer)
     (SIGIOT integer)
     (SIGKILL integer)
     (SIGPIPE integer)
     (SIGPOLL integer)
     (SIGPROF integer)
     (SIGPWR integer)
     (SIGQUIT integer)
     (SIGSEGV integer)
     (SIGSTKFLT integer)
     (SIGSTOP integer)
     (SIGTERM integer)
     (SIGTRAP integer)
     (SIGTSTP integer)
     (SIGTTIN integer)
     (SIGTTOU integer)
     (SIGURG integer)
     (SIGUSR1 integer)
     (SIGUSR2 integer)
     (SIGVTALRM integer)
     (SIGWINCH integer)
     (SIGXCPU integer)
     (SIGXFSZ integer)
     (SIG_BLOCK integer)
     (SIG_SETMASK integer)
     (SIG_UNBLOCK integer)
     (W_OK integer)
     (X_OK integer)
     (acons (lambda (key value alist) alist))
     (acosh (lambda (z) z))
     (add-load-path (lambda (path) undefined))
     (add-method! (lambda (generic method) undefined))
     (all-modules (lambda () list))
     (allocate-instance (lambda (class list)))
     (and-let* (syntax))
     (any (lambda (pred list)))
     (any$ (lambda (pred) proc))
     (any-pred (lambda (pred \.\.\.) pred))
     (append! (lambda (list \.\.\.) list))
     (apply$ (lambda (proc) proc))
     (apply-generic (lambda (generic list)))
     (apply-method (lambda (method list)))
     (apply-methods (lambda (generic list list)))
     (arity (lambda (proc) n))
     (arity-at-least-value (lambda (n)))
     (arity-at-least? (lambda (proc) bool))
     (ash (lambda (n i) n))
     (asinh (lambda (z) z))
     (assoc$ (lambda (obj) proc))
     (atanh (lambda (z) z))
     (autoload (syntax))
     (begin0 (syntax))
     (bignum? (lambda (obj) bool))
     (bit-field (lambda (n start end) n))
     (byte-ready? (lambda (:optional input-port) bool))
     (call-with-input-string (lambda (str proc)))
     (call-with-output-string (lambda (proc) str))
     (call-with-string-io (lambda (str proc) str))
     (case-lambda (syntax))
     (change-class (lambda (obj new-class)))
     (change-object-class (lambda (obj orig-class new-class)))
     (char->ucs (lambda (ch) int))
     (char-set (lambda (ch \.\.\.) char-set))
     (char-set-contains? (lambda (char-set ch) bool))
     (char-set-copy (lambda (char-set) char-set))
     (char-set? (lambda (obj) bool))
     (check-arg (syntax))
     (circular-list? (lambda (obj) bool))
     (clamp (lambda (x1 :optional min-x max-x) x2))
     (class-direct-methods (lambda (class) list))
     (class-direct-slots (lambda (class) list))
     (class-direct-subclasses (lambda (class) list))
     (class-direct-supers (lambda (class) list))
     (class-name (lambda (class) sym))
     (class-of (lambda (obj) class))
     (class-precedence-list (lambda (class) list))
     (class-slot-accessor (lambda (class id) proc))
     (class-slot-bound? (lambda (class id) bool))
     (class-slot-definition (lambda (class id)))
     (class-slot-ref (lambda (class slot)))
     (class-slot-set! (lambda (class slot val) undefined))
     (class-slots (lambda (class) list))
     (closure-code (lambda (proc)))
     (closure? (lambda (obj) bool))
     (compare (lambda (obj1 obj2) n))
     (complement (lambda (proc) proc))
     (compose (lambda (proc \.\.\.) proc))
     (compute-applicable-methods (lambda (generic list)))
     (compute-cpl (lambda (generic list)))
     (compute-get-n-set (lambda (class slot)))
     (compute-slot-accessor (lambda (class slot)))
     (compute-slots (lambda (class)))
     (cond-expand (syntax))
     (condition (syntax))
     (condition-has-type? (lambda (condition obj)))
     (condition-ref (lambda (condition id)))
     (condition-type? (lambda (obj) bool))
     (condition? (lambda (obj) bool))
     (copy-bit (lambda (index n i) n))
     (copy-bit-field (lambda (n start end from) n))
     (copy-port (lambda (from-port to-port :optional unit-sym) undefined))
     (cosh (lambda (z) z))
     (count$ (lambda (pred) proc))
     (current-class-of (lambda (obj) class))
     (current-error-port (lambda () output-port))
     (current-exception-handler (lambda () handler))
     (current-load-history (lambda () list))
     (current-load-next (lambda () list))
     (current-load-port (lambda () port))
     (current-module (lambda () env))
     (current-thread (lambda () thread))
     (current-time (lambda () time))
     (cut (syntax))
     (cute (lambda (args \.\.\.) proc))
     (debug-print (lambda (obj)))
     (debug-print-width (lambda () int))
     (debug-source-info (lambda (obj)))
     (dec! (syntax))
     (decode-float (lambda (x1) vector))
     (define-class (syntax))
     (define-condition-type (syntax))
     (define-constant (syntax))
     (define-generic (syntax))
     (define-in-module (syntax))
     (define-inline (syntax))
     (define-macro (syntax))
     (define-method (syntax))
     (define-module (syntax))
     (define-reader-ctor (lambda (sym proc) undefined))
     (define-values (syntax))
     (delete$ (lambda (obj) proc))
     (delete-keyword (lambda (id list) list))
     (delete-keyword! (lambda (id list) list))
     (delete-method! (lambda (generic method) undefined))
     (digit->integer (lambda (ch) n))
     (disasm (lambda (proc) undefined))
     (dolist (syntax))
     (dotimes (syntax))
     (dotted-list? (lambda (obj) bool))
     (dynamic-load (lambda (file)))
     (eager (lambda (obj)))
     (eq-hash (lambda (obj)))
     (eqv-hash (lambda (obj)))
     (error (lambda (msg-string args \.\.\.)))
     (errorf (lambda (fmt-string args \.\.\.)))
     (eval-when (syntax))
     (every$ (lambda (pred) pred))
     (every-pred (lambda (pred \.\.\.) pred))
     (exit (lambda (:optional n) undefined))
     (export (syntax))
     (export-all (syntax))
     (export-if-defined (syntax))
     (extend (syntax))
     (extract-condition (lambda (condition type)))
     (file-exists? (lambda (filename) bool))
     (file-is-directory? (lambda (filename) bool))
     (file-is-regular? (lambda (filename) bool))
     (filter$ (lambda (pred) proc))
     (find (lambda (pred list)))
     (find$ (lambda (pred) proc))
     (find-module (lambda (id) env))
     (find-tail$ (lambda (pred) proc))
     (fixnum? (lambda (obj) bool))
     (flonum? (lambda (obj) bool))
     (fluid-let (syntax))
     (flush (lambda (:optional output-port) undefined))
     (flush-all-ports (lambda () undefined))
     (fmod (lambda (x1 x2) x3))
     (fold (lambda (proc init list)))
     (fold$ (lambda (proc :optional init) proc))
     (fold-right (lambda (proc init list)))
     (fold-right$ (lambda (proc :optional init)))
     (for-each$ (lambda (proc) (lambda (ls) undefined)))
     (foreign-pointer-attribute-get (lambda (ptr attr)))
     (foreign-pointer-attribute-set (lambda (ptr attr val)))
     (foreign-pointer-attributes (lambda (ptr) list))
     (format (lambda (fmt-string arg \.\.\.)))
     (format/ss (lambda (fmt-string arg \.\.\.)))
     (frexp (lambda (x1) x2))
     (gauche-architecture (lambda () string))
     (gauche-architecture-directory (lambda () string))
     (gauche-character-encoding (lambda () symbol))
     (gauche-dso-suffix (lambda () string))
     (gauche-library-directory (lambda () string))
     (gauche-site-architecture-directory (lambda () string))
     (gauche-site-library-directory (lambda () string))
     (gauche-version (lambda () string))
     (gc (lambda () undefined))
     (gc-stat (lambda () list))
     (gensym (lambda (:optional name) symbol))
     (get-keyword (lambda (id list :optional default)))
     (get-keyword* (syntax))
     (get-optional (syntax))
     (get-output-string (lambda (string-output-port) string))
     (get-remaining-input-string (lambda (port) string))
     (get-signal-handler (lambda (n) proc))
     (get-signal-handler-mask (lambda (n) n))
     (get-signal-handlers (lambda () list))
     (get-signal-pending-limit (lambda () n))
     (getter-with-setter (lambda (get-proc set-proc) proc))
     (global-variable-bound? (lambda (sym) bool))
     (global-variable-ref (lambda (sym)))
     (guard (syntax))
     (has-setter? (lambda (proc) bool))
     (hash (lambda (obj)))
     (hash-table (lambda (id pair \.\.\.) hash-table))
     (hash-table-delete! (lambda (hash-table key) undefined))
     (hash-table-exists? (lambda (hash-table key) bool))
     (hash-table-fold (lambda (hash-table proc init)))
     (hash-table-for-each (lambda (hash-table proc) undefined))
     (hash-table-get (lambda (hash-table key :optional default)))
     (hash-table-keys (lambda (hash-table) list))
     (hash-table-map (lambda (hash-table proc) list))
     (hash-table-num-entries (lambda (hash-table) n))
     (hash-table-pop! (lambda (hash-table key :optional default)))
     (hash-table-push! (lambda (hash-table key value) undefined))
     (hash-table-put! (lambda (hash-table key value) undefined))
     (hash-table-stat (lambda (hash-table) list))
     (hash-table-type (lambda (hash-table) id))
     (hash-table-update! (lambda (hash-table key proc :optional default) undefined))
     (hash-table-values (lambda (hash-table) list))
     (hash-table? (lambda (obj) bool))
     (identifier->symbol (lambda (obj) sym))
     (identifier? (lambda (obj) bool))
     (identity (lambda (obj)))
     (import (syntax))
     (inc! (syntax))
     (inexact-/ (lambda (x1 x2) x3))
     (initialize (lambda (obj)))
     (instance-slot-ref (lambda (obj id)))
     (instance-slot-set (lambda (obj id value)))
     (integer->digit (lambda (n) ch))
     (integer-length (lambda (n) n))
     (is-a? (lambda (obj class) bool))
     (keyword->string (lambda (id) string))
     (keyword? (lambda (obj) bool))
     (last-pair (lambda (pair) pair))
     (lazy (syntax))
     (ldexp (lambda (x1 n) x2))
     (let-keywords* (syntax))
     (let-optionals* (syntax))
     (let/cc (syntax))
     (let1 (syntax))
     (library-exists? (lambda (filename) bool))
     (library-fold (lambda (string proc init)))
     (library-for-each (lambda (string proc) undefined))
     (library-has-module? (lambda (filename id) bool))
     (library-map (lambda (string proc) list))
     (list* (lambda (obj \.\.\.) list))
     (list-copy (lambda (list) list))
     (logand (lambda (n \.\.\.) n))
     (logbit? (lambda (index n) bool))
     (logcount (lambda (n) n))
     (logior (lambda (n \.\.\.) n))
     (lognot (lambda (n) n))
     (logtest (lambda (n \.\.\.) bool))
     (logxor (lambda (n \.\.\.) n))
     (macroexpand (lambda (obj)))
     (macroexpand-1 (lambda (obj)))
     (make (lambda (class args \.\.\.)))
     (make-byte-string (lambda (n :optional int) byte-string))
     (make-compound-condition (lambda (condition \.\.\.) condition))
     (make-condition (lambda (condition-type field+value \.\.\.) condition))
     (make-condition-type (lambda (id condition-type list) condition-type))
     (make-hash-table (lambda (:optional id) hash-table))
     (make-keyword (lambda (string) sym))
     (make-list (lambda (n :optional init) list))
     (make-module (lambda (id :optional if-exists-proc) env))
     (make-weak-vector (lambda (n) vector))
     (map$ (lambda (proc) proc))
     (member$ (lambda (obj) proc))
     (merge (lambda (list1 list2 proc) list))
     (merge! (lambda (list1 list2 proc) list))
     (method-more-specific? (lambda (method1 method2 list) bool))
     (min&max (lambda (x1 \.\.\.) (values x2 x3)))
     (modf (lambda (x1) x2))
     (module-exports (lambda (env) list))
     (module-imports (lambda (env) list))
     (module-name (lambda (env) sym))
     (module-name->path (lambda (sym) string))
     (module-parents (lambda (env) list))
     (module-precedence-list (lambda (env) list))
     (module-table (lambda (env) hash-table))
     (module? (lambda (obj) bool))
     (null-list? (lambda (obj) bool))
     (object-* (lambda (z \.\.\.) z))
     (object-+ (lambda (z \.\.\.) z))
     (object-- (lambda (z \.\.\.) z))
     (object-/ (lambda (z \.\.\.) z))
     (object-apply (lambda (proc arg \.\.\.)))
     (object-compare (lambda (obj1 obj2) n))
     (object-equal? (lambda (obj1 obj2) bool))
     (object-hash (lambda (obj) n))
     (open-coding-aware-port (lambda (input-port) input-port))
     (open-input-buffered-port (lambda ()))
     (open-input-fd-port (lambda (fileno) input-port))
     (open-input-string (lambda (str) input-port))
     (open-output-buffered-port (lambda ()))
     (open-output-fd-port (lambda (fileno) output-port))
     (open-output-string (lambda () string-output-port))
     (pa$ (lambda (proc arg \.\.\.) proc))
     (partition$ (lambda (pred) proc))
     (path->module-name (lambda (str) sym))
     (peek-byte (lambda (:optional input-port) n))
     (pop! (syntax (list)))
     (port->byte-string (lambda (input-port) byte-string))
     (port->list (lambda (proc input-port) list))
     (port->sexp-list (lambda (port) list))
     (port->string (lambda (port) string))
     (port->string-list (lambda (port) list))
     (port-buffering (lambda (port) sym))
     (port-closed? (lambda (port) bool))
     (port-current-line (lambda (port) n))
     (port-file-number (lambda (port) n))
     (port-fold (lambda (proc init port)))
     (port-fold-right (lambda (proc init port)))
     (port-for-each (lambda (proc read-proc) undefined))
     (port-map (lambda (proc read-proc)))
     (port-name (lambda (port) name))
     (port-position-prefix (lambda ()))
     (port-seek (lambda (port offset (set int SEEK_SET SEEK_CUR SEEK_END))))
     (port-tell (lambda (port) n))
     (port-type (lambda (port) sym))
     (print (lambda (obj \.\.\.)))
     (procedure-arity-includes? (lambda (proc n) bool))
     (procedure-info (lambda (proc)))
     (profiler-reset (lambda () undefined))
     (profiler-show (lambda () undefined))
     (profiler-show-load-stats (lambda () undefined))
     (profiler-start (lambda () undefined))
     (profiler-stop (lambda () undefined))
     (program (syntax))
     (promise-kind (lambda ()))
     (promise? (lambda (obj) bool))
     (proper-list? (lambda (obj) bool))
     (provide (lambda (str) undefined))
     (provided? (lambda (str) bool))
     (push! (syntax))
     (quotient&remainder (lambda (n1 n2) (values n1 n2)))
     (raise (lambda (exn) undefined))
     (read-block (lambda (n :optional input-port) string))
     (read-byte (lambda (:optional input-port) n))
     (read-eval-print-loop (lambda () undefined))
     (read-from-string (lambda (str)))
     (read-line (lambda (:optional input-port) str))
     (read-list (lambda (ch :optional input-port)))
     (read-reference-has-value? (lambda ()))
     (read-reference-value (lambda ()))
     (read-reference? (lambda ()))
     (read-with-shared-structure (lambda (:optional input-port)))
     (read/ss (lambda (:optional input-port)))
     (rec (syntax))
     (receive (syntax))
     (redefine-class! (lambda ()))
     (reduce$ (lambda (proc :optional default) proc))
     (reduce-right$ (lambda (proc :optional default) proc))
     (ref (lambda (obj key \.\.\.)))
     (ref* (lambda (obj key \.\.\.)))
     (regexp->string (lambda (regexp) string))
     (regexp-case-fold? (lambda (regexp) bool))
     (regexp-compile (lambda (str) regexp))
     (regexp-optimize (lambda (str) str))
     (regexp-parse (lambda (str) list))
     (regexp-quote (lambda (str) str))
     (regexp-replace (lambda (regexp string subst) string))
     (regexp-replace* (lambda (string regexp subst \.\.\.) string))
     (regexp-replace-all (lambda (regexp string subst) string))
     (regexp-replace-all* (lambda (string regexp subst \.\.\.)))
     (regexp? (lambda (obj) bool))
     (regmatch? (lambda (obj) bool))
     (remove$ (lambda (pred) proc))
     (report-error (lambda ()))
     (require (syntax))
     (require-extension (syntax))
     (reverse! (lambda (list) list))
     (rxmatch (lambda (regexp string) regmatch))
     (rxmatch-after (lambda (regmatch :optional i) str))
     (rxmatch-before (lambda (regmatch :optional i) str))
     (rxmatch-case (syntax))
     (rxmatch-cond (syntax))
     (rxmatch-end (lambda (regmatch :optional i) n))
     (rxmatch-if (syntax))
     (rxmatch-let (syntax))
     (rxmatch-num-matches (lambda (regmatch) i))
     (rxmatch-start (lambda (regmatch :optional i) n))
     (rxmatch-substring (lambda (regmatch :optional i) str))
     (seconds->time (lambda (x1) time))
     (select-module (syntax))
     (set!-values (syntax))
     (set-signal-handler! (lambda (signals handler) undefined))
     (set-signal-pending-limit (lambda (n) undefined))
     (setter (lambda (proc) proc))
     (sinh (lambda (z) z))
     (slot-bound-using-accessor? (lambda (proc obj id) bool))
     (slot-bound-using-class? (lambda (class obj id) bool))
     (slot-bound? (lambda (obj id) bool))
     (slot-definition-accessor (lambda ()))
     (slot-definition-allocation (lambda ()))
     (slot-definition-getter (lambda ()))
     (slot-definition-name (lambda ()))
     (slot-definition-option (lambda ()))
     (slot-definition-options (lambda ()))
     (slot-definition-setter (lambda ()))
     (slot-exists-using-class? (lambda (class obj id) bool))
     (slot-exists? (lambda (obj id) bool))
     (slot-initialize-using-accessor! (lambda ()))
     (slot-missing (lambda (class obj id)))
     (slot-push! (lambda (obj id value) undefined))
     (slot-ref (lambda (obj id)))
     (slot-ref-using-accessor (lambda (proc obj id)))
     (slot-ref-using-class (lambda (class obj id)))
     (slot-set! (lambda (obj id value) undefined))
     (slot-set-using-accessor! (lambda (proc obj id value) undefined))
     (slot-set-using-class! (lambda (class obj id value) undefined))
     (slot-unbound (lambda (class obj id)))
     (sort (lambda (seq :optional proc)))
     (sort! (lambda (seq :optional proc)))
     (sort-applicable-methods (lambda ()))
     (sorted? (lambda (seq :optional proc)))
     (split-at (lambda (list i) (values list list)))
     (stable-sort (lambda (seq :optional proc)))
     (stable-sort! (lambda (seq :optional proc)))
     (standard-error-port (lambda () output-port))
     (standard-input-port (lambda () input-port))
     (standard-output-port (lambda () output-port))
     (string->regexp (lambda (str) regexp))
     (string-byte-ref (lambda (str i) n))
     (string-byte-set! (lambda (str i n) undefined))
     (string-complete->incomplete (lambda (str) str))
     (string-immutable? (lambda (str) bool))
     (string-incomplete->complete (lambda (str) str))
     (string-incomplete->complete! (lambda (str) str))
     (string-incomplete? (lambda (str) bool))
     (string-interpolate (lambda (str) list))
     (string-join (lambda (list :optional delim-str (set grammar infix strict-infix prefix suffix))))
;; deprecated
;;      (string-pointer-byte-index (lambda ()))
;;      (string-pointer-copy (lambda ()))
;;      (string-pointer-index (lambda ()))
;;      (string-pointer-next! (lambda ()))
;;      (string-pointer-prev! (lambda ()))
;;      (string-pointer-ref (lambda ()))
;;      (string-pointer-set! (lambda ()))
;;      (string-pointer-substring (lambda ()))
;;      (string-pointer? (lambda ()))
     (string-scan (lambda (string item :optional (set return index before after before* after* both))))
     (string-size (lambda (str) n))
     (string-split (lambda (str splitter) list))
     (string-substitute! (lambda ()))
     (subr? (lambda (obj) bool))
     (supported-character-encoding? (lambda (id) bool))
     (supported-character-encodings (lambda () list))
     (symbol-bound? (lambda (id) bool))
     (syntax-error (syntax))
     (syntax-errorf (syntax))
     (sys-abort (lambda () undefined))
     (sys-access (lambda (filename (flags amode R_OK W_OK X_OK F_OK))))
     (sys-alarm (lambda (x1) x2))
     (sys-asctime (lambda (time) str))
     (sys-basename (lambda (filename) str))
     (sys-chdir (lambda (dirname)))
     (sys-chmod (lambda (filename n)))
     (sys-chown (lambda (filename uid gid)))
     (sys-close (lambda (fileno)))
     (sys-crypt (lambda (key-str salt-str) str))
     (sys-ctermid (lambda () string))
     (sys-ctime (lambda (time) string))
     (sys-difftime (lambda (time1 time2) x1))
     (sys-dirname (lambda (filename) string))
     (sys-exec (lambda (command-string list) n))
     (sys-exit (lambda (n) undefined))
     (sys-fchmod (lambda (port-or-fileno n)))
     (sys-fdset-max-fd (lambda (fdset)))
     (sys-fdset-ref (lambda (fdset port-or-fileno)))
     (sys-fdset-set! (lambda (fdset port-or-fileno)))
     (sys-fork (lambda () n))
     (sys-fork-and-exec (lambda (command-string list) n))
     (sys-fstat (lambda (port-or-fileno) sys-stat))
     (sys-ftruncate (lambda (port-or-fileno n)))
     (sys-getcwd (lambda () string))
     (sys-getdomainname (lambda () string))
     (sys-getegid (lambda () gid))
     (sys-getenv (lambda (name) string))
     (sys-geteuid (lambda () uid))
     (sys-getgid (lambda () gid))
     (sys-getgrgid (lambda () gid))
     (sys-getgrnam (lambda (name)))
     (sys-getgroups (lambda () list))
     (sys-gethostname (lambda () string))
     (sys-getloadavg (lambda () list))
     (sys-getlogin (lambda () string))
     (sys-getpgid (lambda () gid))
     (sys-getpgrp (lambda () gid))
     (sys-getpid (lambda () pid))
     (sys-getppid (lambda () pid))
     (sys-getpwnam (lambda (name)))
     (sys-getpwuid (lambda () uid))
     (sys-gettimeofday (lambda () (values x1 x2)))
     (sys-getuid (lambda () uid))
     (sys-gid->group-name (lambda (gid) name))
     (sys-glob (lambda (string) list))
     (sys-gmtime (lambda (time) string))
     (sys-group-name->gid (lambda (name) gid))
     (sys-isatty (lambda (port-or-fileno) bool))
     (sys-kill (lambda (pid)))
     (sys-lchown (lambda (filename uid gid)))
     (sys-link (lambda (old-filename new-filename)))
     (sys-localeconv (lambda () alist))
     (sys-localtime (lambda (time) string))
     (sys-lstat (lambda (filename) sys-stat))
     (sys-mkdir (lambda (dirname)))
     (sys-mkfifo (lambda (filename)))
     (sys-mkstemp (lambda (filename)))
     (sys-mktime (lambda (time) x1))
     (sys-nanosleep (lambda (x1)))
     (sys-normalize-pathname (lambda (filename) string))
     (sys-pause (lambda (x1)))
     (sys-pipe (lambda (:optional buffering) (values input-port output-port)))
     (sys-putenv (lambda (name string)))
     (sys-random (lambda () n))
     (sys-readdir (lambda (dirname) list))
     (sys-readlink (lambda (filename) string))
     (sys-realpath (lambda (filename) string))
     (sys-remove (lambda (filename)))
     (sys-rename (lambda (old-filename new-filename)))
     (sys-rmdir (lambda (dirname)))
     (sys-select (lambda (read-filenos write-filenos execpt-filenos :optional timeout-x)))
     (sys-select! (lambda (read-filenos write-filenos execpt-filenos :optional timeout-x)))
     (sys-setenv (lambda (name string)))
     (sys-setgid (lambda (gid)))
     (sys-setlocale (lambda (locale-string)))
     (sys-setpgid (lambda (gid)))
     (sys-setsid (lambda ()))
     (sys-setuid (lambda (uid)))
     (sys-sigmask (lambda ((set how SIG_SETMASK SIG_BLOCK SIG_UNBLOCK) sigset)))
     (sys-signal-name (lambda (n)))
     (sys-sigset (lambda (n \.\.\.) sigset))
     (sys-sigset-add! (lambda (sigset n)))
     (sys-sigset-delete! (lambda (sigset n)))
     (sys-sigset-empty! (lambda (sigset)))
     (sys-sigset-fill! (lambda (sigset)))
     (sys-sigsuspend (lambda (sigset)))
     (sys-sigwait (lambda (sigset)))
     (sys-sleep (lambda (x1)))
     (sys-srandom (lambda (n)))
     (sys-stat (lambda (filename)))
;; deprecated
;;      (sys-stat->atime (lambda ()))
;;      (sys-stat->ctime (lambda ()))
;;      (sys-stat->dev (lambda ()))
;;      (sys-stat->file-type (lambda ()))
;;      (sys-stat->gid (lambda ()))
;;      (sys-stat->ino (lambda ()))
;;      (sys-stat->mode (lambda ()))
;;      (sys-stat->mtime (lambda ()))
;;      (sys-stat->nlink (lambda ()))
;;      (sys-stat->rdev (lambda ()))
;;      (sys-stat->size (lambda ()))
;;      (sys-stat->type (lambda ()))
;;      (sys-stat->uid (lambda ()))
     (sys-strerror (lambda (errno) string))
     (sys-strftime (lambda (format-string time)))
     (sys-symlink (lambda (old-filename new-filename)))
     (sys-system (lambda (command) n))
     (sys-time (lambda () n))
     (sys-times (lambda () list))
;;      (sys-tm->alist (lambda ()))
     (sys-tmpnam (lambda () string))
     (sys-truncate (lambda (filename n)))
     (sys-ttyname (lambda (port-or-fileno) string))
     (sys-uid->user-name (lambda (uid) name))
     (sys-umask (lambda () n))
     (sys-uname (lambda () string))
     (sys-unlink (lambda (filename)))
     (sys-unsetenv (lambda (name)))
     (sys-user-name->uid (lambda (name) uid))
     (sys-utime (lambda (filename)))
     (sys-wait (lambda ()))
     (sys-wait-exit-status (lambda (n) n))
     (sys-wait-exited? (lambda (n) bool))
     (sys-wait-signaled? (lambda (n) bool))
     (sys-wait-stopped? (lambda (n) bool))
     (sys-wait-stopsig (lambda (n) n))
     (sys-wait-termsig (lambda (n) n))
     (sys-waitpid (lambda (pid)))
     (tanh (lambda (z) z))
     (time (syntax))
     (time->seconds (lambda (time) x1))
     (time? (lambda (obj) bool))
     (toplevel-closure? (lambda (obj) bool))
     (touch-instance! (lambda ()))
     (ucs->char (lambda (n) ch))
     (undefined (lambda () undefined))
     (undefined? (lambda (obj) bool))
     (unless (syntax))
     (until (syntax))
     (unwrap-syntax (lambda (obj)))
     (update! (syntax))
     (update-direct-method! (lambda ()))
     (update-direct-subclass! (lambda ()))
     (use (special symbol scheme-gauche-available-modules))
     (use-version (syntax))
     (values-ref (syntax))
     (vector-copy (lambda (vector :optional start end fill) vector))
     (vm-dump (lambda () undefined))
     (vm-get-stack-trace (lambda () undefined))
     (vm-get-stack-trace-lite (lambda () undefined))
     (vm-set-default-exception-handler (lambda (handler) undefined))
     (warn (lambda (message-str args) undefined))
     (weak-vector-length (lambda (vector) n))
     (weak-vector-ref (lambda (vector i)))
     (weak-vector-set! (lambda (vector i value) undefined))
     (when (syntax))
     (while (syntax))
     (with-error-handler (lambda (handler thunk)))
     (with-error-to-port (lambda (port thunk)))
     (with-exception-handler (lambda (handler thunk)))
     (with-input-from-port (lambda (port thunk)))
     (with-input-from-string (lambda (string thunk)))
     (with-module (syntax))
     (with-output-to-port (lambda (port thunk)))
     (with-output-to-string (lambda (thunk) string))
     (with-port-locking (lambda (port thunk)))
     (with-ports (lambda (input-port output-port error-port thunk)))
     (with-signal-handlers (syntax))
     (with-string-io (lambda (string thunk) string))
     (write* (lambda (obj :optional output-port) undefined))
     (write-byte (lambda (n :optional output-port) undefined))
     (write-limited (lambda (obj :optional output-port)))
     (write-object (lambda (obj output-port)))
     (write-to-string (lambda (obj) string))
     (write-with-shared-structure (lambda (obj :optional output-port)))
     (write/ss (lambda (obj :optional output-port)))
     (x->integer (lambda (obj) integer))
     (x->number (lambda (obj) number))
     (x->string (lambda (obj) string))
     )))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; special lookups (XXXX add more impls, try to abstract better)

(defvar *scheme-chicken-base-repo*
  (or (getenv "CHICKEN_REPOSITORY")
      (let ((dir
             (car (remove-if-not #'file-directory-p
                                 '("/usr/lib/chicken"
                                   "/usr/local/lib/chicken"
                                   "/opt/lib/chicken"
                                   "/opt/local/lib/chicken")))))
        (and dir
             (car (reverse (sort (directory-files dir t "^[0-9]+$")
                                 #'string-lessp)))))
      (and (fboundp 'shell-command-to-string)
           (let* ((res (shell-command-to-string "chicken-setup -R"))
                  (res (substring res 0 (- (length res) 1))))
             (and res (file-directory-p res) res)))
      "/usr/local/lib/chicken"))

(defvar *scheme-chicken-repo-dirs*
  (remove-if-not
   #'(lambda (x) (and (stringp x) (not (equal x ""))))
   (let ((home (getenv "CHICKEN_HOME")))
     (if (and home (not (equal home "")))
         (let ((res (split-string home ";")))
           (if (member *scheme-chicken-repo-dirs* res)
               res
             (cons *scheme-chicken-repo-dirs* res))) 
       (list *scheme-chicken-base-repo*)))))

(defun scheme-chicken-available-modules (&optional sym)
  (append
   (mapcar #'symbol-name (mapcar #'car *scheme-chicken-modules*))
   (mapcar
    #'file-name-sans-extension
    (directory-files "." nil ".*\\.scm$" t))
   (scheme-append-map
    #'(lambda (dir)
        (mapcar
         #'file-name-sans-extension
         (directory-files dir nil ".*\\.\\(so\\|scm\\)$" t)))
    *scheme-chicken-repo-dirs*)))

(defvar *scheme-gauche-repo-path*
  (or (car (remove-if-not #'file-directory-p
                          '("/usr/share/gauche"
                            "/usr/local/share/gauche"
                            "/opt/share/gauche"
                            "/opt/local/share/gauche")))
      (and (fboundp 'shell-command-to-string)
           (let* ((res (shell-command-to-string "gauche-config --syslibdir"))
                  (res (substring res 0 (- (length res) 1))))
             (and res (file-directory-p res)
                  (let* ((dir (file-name-directory res))
                         (dir2 (file-name-directory
                                (substring dir 0 (- (length dir) 1)))))
                    (substring dir2 0 (- (length dir2) 1))))))
      "/usr/local/share/gauche"))

(defvar *scheme-gauche-site-repo-path*
  (concat *scheme-gauche-repo-path* "/site/lib"))

(defun scheme-gauche-available-modules (&optional sym)
  (let ((version-dir
         (concat
          (car (directory-files *scheme-gauche-repo-path* t "^[0-9]"))
          "/lib"))
        (site-dir *scheme-gauche-site-repo-path*)
        (other-dirs
         (remove-if-not
          #'(lambda (d) (and (not (equal d "")) (file-directory-p d)))
          (split-string (or (getenv "GAUCHE_LOAD_PATH") "") ":"))))
    (mapcar
     #'(lambda (f) (subst-char-in-string ?/ ?. f))
     (mapcar
      #'file-name-sans-extension
      (scheme-append-map
       #'(lambda (dir)
           (let ((len (length dir)))
             (mapcar #'(lambda (f) (substring f (+ 1 len)))
                     (scheme-directory-tree-files dir t "\\.scm"))))
       (cons version-dir (cons site-dir other-dirs)))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; utilities

(defun scheme-append-map (proc init-ls)
  (if (null init-ls)
      '()
    (let* ((ls (reverse init-ls))
           (res (funcall proc (pop ls))))
      (while (consp ls)
        (setq res (append (funcall proc (pop ls)) res)))
      res)))

(defun scheme-flatten (ls)
  (cond
   ((consp ls) (cons (car ls) (scheme-flatten (cdr ls))))
   ((null ls) '())
   (t (list ls))))

(defun scheme-in-string-p ()
  (let ((orig (point)))
    (save-excursion
      (goto-char (point-min))
      (let ((parses (parse-partial-sexp (point) orig)))
        (nth 3 parses)))))

(defun scheme-beginning-of-sexp ()
  (let ((syn (char-syntax (char-before (point)))))
    (if (or (eq syn ?\()
	    (and (eq syn ?\") (scheme-in-string-p)))
	(forward-char -1)
      (forward-sexp -1))))

(defun scheme-find-file-in-path (file path)
  (car (remove-if-not
        #'(lambda (dir) (file-exists-p (concat dir "/" file)))
        path)))

;; visit a file and kill the buffer only if it wasn't already open
(defmacro scheme-with-find-file (path-expr &rest body)
  (let ((path (gensym))
        (buf (gensym))
        (res (gensym)))
    `(save-window-excursion
       (let* ((,path (file-truename ,path-expr))
              (,buf (find-if #'(lambda (x) (equal ,path (buffer-file-name x)))
                             (buffer-list))))
         (if ,buf
             (switch-to-buffer ,buf)
           (switch-to-buffer (find-file-noselect ,path t t)))
         (let ((,res (save-excursion ,@body)))
           (unless ,buf (kill-buffer (current-buffer)))
           ,res)))))

(defun scheme-directory-tree-files (init-dir &optional full match)
  (let ((res '())
        (stack (list init-dir)))
    (while (consp stack)
      (let* ((dir (pop stack))
             (files (cddr (directory-files dir full))))
        (setq res (append (if match
                              (remove-if-not
                               #'(lambda (f) (string-match match f))
                               files)
                            files)
                          res))
        (setq stack
              (append
               (remove-if-not 'file-directory-p
                              (if full
                                  files
                                (mapcar #'(lambda (f) (concat dir "/" f))
                                        files)))
               stack))))
    res))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; sexp manipulation

;; returns current argument position within sexp
(defun scheme-beginning-of-current-sexp-operator ()
  (let ((pos 0))
    (skip-syntax-backward "w_")
    (while (and (not (bobp)) (not (eq ?\( (char-before))))
      (scheme-beginning-of-sexp)
      (incf pos))
    pos))

(defun scheme-beginning-of-next-sexp ()
  (forward-sexp 2)
  (backward-sexp 1))

(defun scheme-beginning-of-string ()
  (interactive)
  (search-backward "\"" nil t)
  (while (and (> (point) (point-min)) (eq ?\\ (char-before)))
    (search-backward "\"" nil t)))

;; for the enclosing sexp, returns a cons of the leading symbol (if
;; any) and the current position within the sexp (starting at 0)
;; (defun scheme-enclosing-sexp-prefix ()
;;   (save-excursion
;;     (let ((pos (scheme-beginning-of-current-sexp-operator)))
;;       (cons (scheme-symbol-at-point) pos))))

(defun scheme-enclosing-2-sexp-prefixes ()
  (save-excursion
    (let* ((pos1 (scheme-beginning-of-current-sexp-operator))
           (sym1 (scheme-symbol-at-point)))
      (backward-char)
      (or
       (ignore-errors
         (let ((pos2 (scheme-beginning-of-current-sexp-operator)))
           (list sym1 pos1 (scheme-symbol-at-point) pos2)))
       (list sym1 pos1 nil 0)))))

;; sexp-at-point is always fragile, both because the user can input
;; incomplete sexps and because some scheme sexps are not valid elisp
;; sexps.  this is one of the few places we use it, so we're careful
;; to wrap it in ignore-errors.
(defun scheme-nth-sexp-at-point (n)
  (ignore-errors
    (save-excursion
      (forward-sexp (+ n 1))
      (let ((end (point)))
        (forward-sexp -1)
        (car (read-from-string (buffer-substring (point) end)))))))

(defun scheme-symbol-at-point ()
  (save-excursion
    (skip-syntax-backward "w_")
    (let ((start (point)))
      (skip-syntax-forward "w_")
      (and (< start (point))
           (intern (buffer-substring start (point)))))))

(defun scheme-goto-next-top-level ()
  (let ((here (point)))
    (or (ignore-errors (end-of-defun) (end-of-defun)
                       (beginning-of-defun)
                       (< here (point)))
        (progn (forward-char) (re-search-forward "^(" nil t))
        (goto-char (point-max)))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; variable extraction

(defun scheme-sexp-type-at-point (&optional env)
  (case (char-syntax (char-after))
    ((?\()
     (forward-char 1)
     (if (eq ?w (char-syntax (char-after)))
         (let ((op (scheme-symbol-at-point)))
           (cond
            ((eq op 'lambda)
             (let ((params
                    (scheme-nth-sexp-at-point 1)))
               `(lambda ,params)))
            (t
             (let ((spec (scheme-env-lookup env op)))
               (and spec
                    (consp (cadr spec))
                    (eq 'lambda (caadr spec))
                    (cddadr spec)
                    (car (cddadr spec)))))))
       nil))
    ((?\")
     'string)
    ((?\w)
     (if (string-match "[0-9]" (string (char-after)))
         'number
       nil))
    (t
     nil)))

(defun scheme-let-vars-at-point (&optional env)
  (let ((end (or (ignore-errors
                   (save-excursion (forward-sexp) (point)))
                 (point-min)))
        (vars '()))
    (forward-char 1)
    (while (< (point) end)
      (when (eq ?\( (char-after))
        (save-excursion
          (forward-char 1)
          (if (eq ?w (char-syntax (char-after)))
              (let* ((sym (scheme-symbol-at-point))
                     (type (ignore-errors
                             (scheme-beginning-of-next-sexp)
                             (scheme-sexp-type-at-point env))))
                (push (if type (list sym type) (list sym)) vars)))))
      (unless (ignore-errors (let ((here (point)))
                               (scheme-beginning-of-next-sexp)
                               (> (point) here)))
        (goto-char end)))
    (reverse vars)))

(defun scheme-extract-match-clause-vars (x)
  (cond
   ((null x) '())
   ((symbolp x)
    (if (memq x '(_ ___ \.\.\.))
        '()
      (list (list x))))
   ((consp x)
    (case (car x)
      ((or not)
       (scheme-extract-match-clause-vars (cdr x)))
      ((and)
       (if (and (consp (cdr x))
                (consp (cddr x))
                (symbolp (cadr x))
                (consp (caddr x))
                (not (memq (caaddr x)
                           '(= $ @ ? and or not quote quasiquote get! set!))))
           (cons (list (cadr x) (if (listp (caddr x)) 'list 'pair))
                 (scheme-extract-match-clause-vars (cddr x)))
         (scheme-extract-match-clause-vars (cddr x))))
      ((= $ @)
       (if (consp (cdr x)) (scheme-extract-match-clause-vars (cddr x)) '()))
      ((\? ? ) ; XXXX this is a hack, the lone ? gets read as a char (space)
       (if (and (consp (cdr x))
                (consp (cddr x))
                (symbolp (cadr x))
                (symbolp (caddr x)))
           (cons (list (caddr x) (scheme-predicate->type (cadr x)))
                 (scheme-extract-match-clause-vars (cdddr x)))
         (scheme-extract-match-clause-vars (cddr x))))
      ((get! set!)
       (if (consp (cdr x)) (scheme-extract-match-clause-vars (cadr x)) '()))
      ((quote) '())
      ((quasiquote) '())                ; XXXX
      (t
       (union (scheme-extract-match-clause-vars (car x))
              (scheme-extract-match-clause-vars (cdr x))))))
   ((vectorp x)
    (scheme-extract-match-clause-vars (concatenate 'list x)))
   (t
    '())))

;; call this from the first opening paren of the match clauses
(defun scheme-extract-match-vars (&optional pos limit)
  (let ((match-vars '())
        (limit (or limit
                   (save-excursion
                     (or
                      (ignore-errors (end-of-defun) (point))
                      (point-max))))))
    (save-excursion
      (while (< (point) limit)
        (let* ((end (ignore-errors (forward-sexp) (point)))
               (start (and end (progn (backward-sexp) (point)))))
          (cond
           ((and pos start end (or (< pos start) (> pos end)))
            (goto-char (if end (+ end 1) limit)))
           (t
            (forward-char 1)
            (let* ((pat (scheme-nth-sexp-at-point 0))
                   (new-vars (ignore-errors
                               (scheme-extract-match-clause-vars pat))))
              (setq match-vars (append new-vars match-vars)))
            (goto-char (if (or pos (not end)) limit (+ end 1)))))))
      match-vars)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; You can set the *scheme-default-implementation* to your preferred
;; implementation, for when we can't figure out the file from
;; heuristics.  Alternately, in any given buffer, just
;;
;; (setq *scheme-current-implementation* whatever)

(defgroup scheme-complete nil
  "Smart tab completion"
  :group 'scheme)

(defcustom scheme-default-implementation nil
  "Default scheme implementation to provide completion for
when scheme-complete can't infer the current implementation."
  :type 'symbol
  :group 'scheme-complete)

(defcustom scheme-complete-smart-indent-p t
  "Toggles using `scheme-smart-indent' for `scheme-complete-or-indent'."
  :type 'boolean
  :group 'scheme-complete)

(defcustom scheme-complete-cache-p t
  "Toggles caching of module/load export information."
  :type 'boolean
  :group 'scheme-complete)

;; (defcustom scheme-complete-learn-syntax-p nil
;;   "Toggles parsing of syntax-rules macros for completion info."
;;   :type 'boolean
;;   :group 'scheme-complete)

(defvar *scheme-complete-module-cache* '())

(defvar *scheme-current-implementation* nil)
(make-variable-buffer-local '*scheme-current-implementation*)

;; most implementations use their name as the script name
(defvar *scheme-interpreter-alist*
  '(("csi"  . chicken)
    ("gosh" . gauche)
    ("gsi"  . gambit)
    ("mred" . mzscheme)
    ))

(defvar *scheme-imported-modules* '())

(defun scheme-current-implementation ()
  (unless *scheme-current-implementation*
    (setq *scheme-current-implementation*
          (save-excursion
            (goto-char (point-min))
            (or
             (and (looking-at "#! *\\([^ \t\n]+\\)")
                  (let ((script (file-name-nondirectory (match-string 1))))
                    (cdr (assoc script *scheme-interpreter-alist*))))
             (cond
              ((re-search-forward "(define-module +\\(.\\)" nil t)
               (if (equal "(" (match-string 1))
                   'guile
                 'gauche))
              ((re-search-forward "(use " nil t)
               'chicken)
              ((re-search-forward
                "\\(?:(module \\|#\\(?:lang\\|reader\\)\\)" nil t)
               'mzscheme))))))
  (or *scheme-current-implementation*
      scheme-default-implementation))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defun scheme-current-local-vars (&optional env)
  (let ((vars '())
        (limit (save-excursion (beginning-of-defun) (+ (point) 1)))
        (start (point))
        (scan-internal))
    (save-excursion
      (while (> (point) limit)
        (or (ignore-errors
              (progn
                (skip-chars-backward " \t\n" limit)
                (scheme-beginning-of-sexp)
                t))
            (goto-char limit))
        (when (and (> (point) (point-min))
                   (eq ?\( (char-syntax (char-before (point))))
                   (eq ?w (char-syntax (char-after (point)))))
          (setq scan-internal t)
          (let ((sym (scheme-symbol-at-point)))
            (case sym
              ((lambda)
               (setq vars
                     (append
                      (mapcar #'list
                              (scheme-flatten (scheme-nth-sexp-at-point 1)))
                      vars)))
              ((match match-let match-let*)
               (setq vars
                     (append
                      (ignore-errors
                        (save-excursion
                          (let ((limit (save-excursion
                                         (cond
                                          ((eq sym 'match)
                                           (backward-char 1)
                                           (forward-sexp 1))
                                          (t
                                           (forward-sexp 2)))
                                         (point))))
                            (forward-sexp 2)
                            (if (eq sym 'match)
                                (forward-sexp 1))
                            (backward-sexp 1)
                            (if (not (eq sym 'match))
                                (forward-char 1))
                            (scheme-extract-match-vars
                             (and (or (eq sym 'match) (< start limit)) start)
                             limit))))
                      vars)))
              ((let let* letrec letrec* let-syntax letrec-syntax and-let* do)
               (or
                (ignore-errors
                  (save-excursion
                    (scheme-beginning-of-next-sexp)
                    (if (and (eq sym 'let)
                             (eq ?w (char-syntax (char-after (point)))))
                        ;; named let
                        (let* ((sym (scheme-symbol-at-point))
                               (args (progn
                                       (scheme-beginning-of-next-sexp)
                                       (scheme-let-vars-at-point env))))
                          (setq vars (cons `(,sym (lambda ,(mapcar #'car args)))
                                           (append args vars))))
                      (setq vars (append (scheme-let-vars-at-point env) vars)))
                    t))
                (goto-char limit)))
              ((let-values let*-values)
               (setq vars
                     (append (mapcar
                              #'list
                              (scheme-append-map
                               #'scheme-flatten
                               (remove-if-not #'consp
                                              (scheme-nth-sexp-at-point 1))))
                             vars)))
              ((receive defun defmacro)
               (setq vars
                     (append (mapcar #'list
                                     (scheme-flatten
                                      (scheme-nth-sexp-at-point 1)))
                             vars)))
              (t
               (if (string-match "^define\\(-.*\\)?" (symbol-name sym))
                   (let ((defs (save-excursion
                                 (backward-char)
                                 (scheme-extract-definitions))))
                     (setq vars
                           (append (scheme-append-map
                                    #'(lambda (x)
                                        (and (consp (cdr x))
                                             (consp (cadr x))
                                             (eq 'lambda (caadr x))
                                             (mapcar #'list
                                                     (scheme-flatten
                                                      (cadadr x)))))
                                    defs)
                                   defs
                                   vars)))
                 (setq scan-internal nil))))
            ;; check for internal defines
            (when scan-internal
              (ignore-errors
                (save-excursion
                  (forward-sexp
                   (+ 1 (if (numberp scan-internal) scan-internal 2)))
                  (backward-sexp)
                  (if (< (point) start)
                      (setq vars (append (scheme-current-definitions) vars))
                    ))))))))
    (reverse vars)))

(defun scheme-extract-import-module-imports (sexp)
  (case (and (consp sexp) (car sexp))
    ((prefix prefix-in)
     (let* ((ids (scheme-extract-import-module-imports (cadr sexp)))
            (prefix0 (caddr sexp))
            (prefix (if (symbolp prefix0) (symbol-name prefix0) prefix0)))
       (mapcar #'(lambda (x)
                   (cons (intern (concat prefix (symbol-name (car x))))
                         (cdr x)))
               ids)))
    ((prefix-all-except)
     (let ((prefix
            (if (symbolp (cadr sexp)) (symbol-name (cadr sexp)) (cadr sexp)))
           (exceptions (cddr sexp)))
       (mapcar #'(lambda (x)
                   (if (memq (car x) exceptions)
                       x
                     (cons (intern (concat prefix (symbol-name (car x))))
                           (cdr x))))
               (scheme-extract-import-module-imports (caddr sexp)))))
    ((for for-syntax for-template for-label for-meta)
     (scheme-extract-import-module-imports (cadr sexp)))
    ((rename rename-in)
     (let ((renames (cddr sexp)))
       (mapcar #'(lambda (x)
                   (cons (or (cadr (assq (car x) renames)) (car x)) (cdr x)))
               (scheme-extract-import-module-imports (cadr sexp)))))
    ((except except-in)
     (remove-if #'(lambda (x) (memq (car x) (cddr sexp)))
                (scheme-extract-import-module-imports (cadr sexp))))
    ((only only-in)
     (remove-if-not
      #'(lambda (x) (memq (car x) (cddr sexp)))
      (scheme-extract-import-module-imports (cadr sexp))))
    ((import import-for-syntax require)
     (scheme-extract-import-module-imports (cadr sexp)))
    ((library)
     (if (and (stringp (cadr sexp)) (file-exists-p (cadr sexp)))
         (scheme-module-exports (intern (cadr sexp)))))
    ((lib)
     (if (and (equal "srfi" (caddr sexp))
              (stringp (cadr sexp))
              (string-match "^[0-9]+\\." (cadr sexp)))
         (scheme-module-exports
          (intern (file-name-sans-extension (concat "srfi-" (cadr sexp)))))
       (scheme-module-exports
        (intern (apply 'concat (append (cddr sexp) (list (cadr sexp))))))))
    (t
     (scheme-module-exports sexp))))

(defun scheme-extract-sexp-imports (sexp)
  (case (and (consp sexp) (car sexp))
    ((begin define-module)
     (scheme-append-map #'scheme-extract-sexp-imports (cdr sexp)))
    ((cond-expand)
     (scheme-append-map #'scheme-extract-sexp-imports
                        (scheme-append-map #'cdr (cdr sexp))))
    ((use require-extension)
     (scheme-append-map #'scheme-module-exports (cdr sexp)))
    ((import)
     (scheme-extract-import-module-imports (cadr sexp)))
    ((autoload)
     (unless (member (cadr sexp) *scheme-imported-modules*)
       (push (cadr sexp) *scheme-imported-modules*)
       (mapcar #'(lambda (x) (cons (if (consp x) (car x) x) '((lambda obj))))
               (cddr sexp))))
    ((load)
     (unless (member (cadr sexp) *scheme-imported-modules*)
       (push (cadr sexp) *scheme-imported-modules*)
       (and (file-exists-p (cadr sexp))
            (scheme-with-find-file (cadr sexp)
              (scheme-current-globals)))))
    ((library module)
     (scheme-append-map #'scheme-extract-import-module-imports
                        (remove-if #'(lambda (x)
                                       (memq (car x) '(import require)))
                                   (cdr sexp))))
    ))

(defun scheme-module-symbol-p (sym)
  (memq sym '(use require require-extension begin cond-expand
              module library define-module autoload load import)))

(defun scheme-skip-shebang ()
  ;; skip shebang if present
  (if (looking-at "#!")
      ;; guile skips until a closing !#
      (if (eq 'guile (scheme-current-implementation))
          (re-search-forward "!#" nil t)
        (next-line))))

(defun scheme-current-imports ()
  (let ((imports '())
        (*scheme-imported-modules* '()))
    (save-excursion
      (goto-char (point-min))
      (scheme-skip-shebang)
      ;; scan for module forms
      (while (not (eobp))
        (if (ignore-errors (progn (forward-sexp) t))
            (let ((end (point)))
              (backward-sexp)
              (when (eq ?\( (char-after))
                (forward-char)
                (when (and (not (eq ?\( (char-after)))
                           (scheme-module-symbol-p (scheme-symbol-at-point)))
                  (backward-char)
                  (ignore-errors
                    (setq imports
                          (append (scheme-extract-sexp-imports
                                   (scheme-nth-sexp-at-point 0))
                                  imports)))))
              (goto-char end))
          ;; if an incomplete sexp is found, try to recover at the
          ;; next line beginning with an open paren
          (scheme-goto-next-top-level))))
    imports))

;; we should be just inside the opening paren of an expression
(defun scheme-name-of-define ()
  (save-excursion
    (scheme-beginning-of-next-sexp)
    (if (eq ?\( (char-syntax (char-after)))
        (forward-char))
    (and (memq (char-syntax (char-after)) '(?\w ?\_))
         (scheme-symbol-at-point))))

(defun scheme-type-of-define ()
  (save-excursion
    (scheme-beginning-of-next-sexp)
    (cond
     ((eq ?\( (char-syntax (char-after)))
      `(lambda ,(cdr (scheme-nth-sexp-at-point 0))))
     (t
      (scheme-beginning-of-next-sexp)
      (scheme-sexp-type-at-point)))))

;; we should be at the opening paren of an expression
(defun scheme-extract-definitions (&optional env)
  (save-excursion
    (let ((sym (ignore-errors (and (eq ?\( (char-syntax (char-after)))
                                   (progn (forward-char)
                                          (scheme-symbol-at-point))))))
      (case sym
        ((define-syntax define-compiled-syntax defmacro define-macro)
         (list (list (scheme-name-of-define) '(syntax))))
        ((define define-inline define-constant define-primitive defun)
         (let ((name (scheme-name-of-define))
               (type (scheme-type-of-define)))
           (list (if type (list name type) (list name)))))
        ((defvar define-class)
         (list (list (scheme-name-of-define) 'non-procedure)))
        ((define-record)
         (backward-char)
         (ignore-errors
           (let* ((sexp (scheme-nth-sexp-at-point 0))
                  (name (symbol-name (cadr sexp))))
             `((,(intern (concat name "?")) (lambda (obj) boolean))
               (,(intern (concat "make-" name)) (lambda ,(cddr sexp) ))
               ,@(scheme-append-map
                  #'(lambda (x)
                      `((,(intern (concat name "-" (symbol-name x)))
                         (lambda (non-procedure)))
                        (,(intern (concat name "-" (symbol-name x) "-set!"))
                         (lambda (non-procedure val) undefined))))
                  (cddr sexp))))))
        ((define-record-type)
         (backward-char)
         (ignore-errors
           (let ((sexp (scheme-nth-sexp-at-point 0)))
             `((,(caaddr sexp) (lambda ,(cdaddr sexp)))
               (,(cadddr sexp) (lambda (obj)))
               ,@(scheme-append-map 
                  #'(lambda (x)
                      (if (consp x)
                          (if (consp (cddr x))
                              `((,(cadr x) (lambda (non-procedure)))
                                (,(caddr x)
                                 (lambda (non-procedure val) undefined)))
                            `((,(cadr x) (lambda (non-procedure)))))))
                  (cddddr sexp))))))
        ((begin progn)
         (forward-sexp)
         (scheme-current-definitions))
        (t
         '())))))

;; a little more liberal than -definitions, we try to scan to a new
;; top-level form (i.e. a line beginning with an open paren) if
;; there's an error during normal sexp movement
(defun scheme-current-globals ()
  (let ((globals '()))
    (save-excursion
      (goto-char (point-min))
      (or (ignore-errors (end-of-defun) (beginning-of-defun) t)
          (re-search-forward "^(" nil t)
          (goto-char (point-max)))
      (while (not (eobp))
        (setq globals
              (append (ignore-errors (scheme-extract-definitions)) globals))
        (scheme-goto-next-top-level)))
    globals))

;; for internal defines, etc.
(defun scheme-current-definitions (&optional enclosing-end)
  (let ((defs '())
        (end (or enclosing-end (point-max))))
    (save-excursion
      (while (< (point) end)
        (let ((here (point))
              (new-defs (scheme-extract-definitions)))
          (cond
           (new-defs
             (setq defs (append new-defs defs))
             (or (ignore-errors (scheme-beginning-of-next-sexp)
                                (> (point) here))
                 (goto-char end)))
           (t ;; non-definition form, stop scanning
            (goto-char end))))))
    defs))

(defun scheme-current-exports ()
  (let ((res '()))
    (save-excursion
      (goto-char (point-min))
      (or (ignore-errors (end-of-defun) (beginning-of-defun) t)
          (re-search-forward "^(" nil t)
          (goto-char (point-max)))
      (while (not (eobp))
        (when (and (eq ?\( (char-syntax (char-after)))
                   (eq ?w (char-syntax (char-after (1+ (point))))))
          (let ((sym (save-excursion (forward-char) (scheme-symbol-at-point))))
            (case sym
              ((declare define-module)
               (let ((decls (scheme-nth-sexp-at-point 0)))
                 (cond
                  ((and (listp decls) (assq 'export decls))
                   (setq res (nconc (cdr (assq 'export decls)) res)))
                  ((and (listp decls) (assq 'export-all decls))
                   (goto-char (point-max))))))
              ((export provide)
               (unless (and (eq 'provide sym)
                            (eq 'chicken (scheme-current-implementation)))
                 (setq res (nconc (cdr (scheme-nth-sexp-at-point 0)) res))))
              ((export-all)
               (goto-char (point-max)))
              ((extend)
               (let ((parents (cdr (scheme-nth-sexp-at-point 0))))
                 (setq res (nconc (mapcar #'car
                                          (scheme-append-map
                                           #'scheme-module-exports
                                           parents))
                                  res))))
              ((module)
               (forward-char)
               (forward-sexp)
               (let ((x (scheme-nth-sexp-at-point 0)))
                 (cond
                  ((eq '* x)
                   (goto-char (point-max)))
                  ((listp x)
                   (setq res
                         (nconc (remove-if-not #'symbolp (cdr x)) res))))))
              )))
        (scheme-goto-next-top-level)))
    res))

(defun scheme-srfi-exports (i)
  (and (integerp i)
       (>= i 0)
       (< i (length *scheme-srfi-info*))
       (let ((info (cdr (aref *scheme-srfi-info* i))))
         (if (and (consp info) (null (cdr info)) (symbolp (car info)))
             (scheme-module-exports (car info))
           info))))

(defvar scheme-module-exports-function nil)

(defvar *scheme-module-exports-functions*
  '((chicken  . scheme-module-exports/chicken)
    (gauche   . scheme-module-exports/gauche)
    (mzscheme . scheme-module-exports/mzscheme)))

(defun scheme-module-exports (mod)
  (unless (member mod *scheme-imported-modules*)
    (push mod *scheme-imported-modules*)
    (cond
     ((and (consp mod) (eq 'srfi (car mod)))
      (scheme-append-map #'scheme-srfi-exports (cdr mod)))
     ((and (symbolp mod) (string-match "^srfi-" (symbol-name mod)))
      (scheme-srfi-exports
       (string-to-number (substring (symbol-name mod) 5))))
     (t
      (let ((cached (assq mod *scheme-complete-module-cache*)))
        ;; remove stale caches
        (when (and cached
                   (stringp (cadr cached))
                   (ignore-errors
                     (let ((mtime (nth 5 (file-attributes (cadr cached))))
                           (ptime (caddr cached)))
                       (or (> (car mtime) (car ptime))
                           (and (= (car mtime) (car ptime))
                                (>= (cadr mtime) (cadr ptime)))))))
          (setq *scheme-complete-module-cache*
                (assq-delete-all mod *scheme-complete-module-cache*))
          (setq cached nil))
        (if cached
            (cadddr cached)
          ;; (re)compute module exports
          (let ((export-fun
                 (or scheme-module-exports-function
                     (cdr (assq (scheme-current-implementation)
                                *scheme-module-exports-functions*)))))
            (when export-fun
              (let ((res (funcall export-fun mod)))
                (when res
                  (when (and scheme-complete-cache-p (car res))
                    (push (list mod
                                (car res)
                                (nth 5 (file-attributes (car res)))
                                (cadr res))
                          *scheme-complete-module-cache*))
                  (cadr res)))))))))))

(defun scheme-module-exports/chicken (mod)
  (let ((predefined (assq mod *scheme-chicken-modules*)))
    (if predefined
        (list nil (cdr predefined))
      (let ((export-file
             (concat *scheme-chicken-base-repo* "/"
                     (symbol-name mod) ".exports"))
            (setup-file
             (concat *scheme-chicken-base-repo* "/"
                     (symbol-name mod) ".setup-info"))
            (source-file
             (concat (symbol-name mod) ".scm")))
        (cond
         ((file-exists-p source-file)
          (list source-file
                (scheme-with-find-file source-file
                  (let ((env (scheme-current-globals))
                        (exports (scheme-current-exports)))
                    (if (consp exports)
                        (remove-if-not #'(lambda (x) (memq (car x) exports)) env)
                        env)))))
         ((file-exists-p export-file)
          (list export-file
                (mapcar #'(lambda (x) (cons (intern x) '((lambda obj))))
                        (scheme-file->lines export-file))))
         ((file-exists-p setup-file)
          (list setup-file
                (mapcar #'(lambda (x) (cons (intern x) '((lambda obj))))
                        (scheme-with-find-file setup-file
                          (let* ((alist (scheme-nth-sexp-at-point 0))
                                 (cell (assq 'exports alist)))
                            (cdr cell))))))
         )))))

(defun scheme-module-exports/gauche (mod)
  (let* ((file (concat (subst-char-in-string ?. ?/ (symbol-name mod)) ".scm"))
         (dir
          (scheme-find-file-in-path
           file
           (cons
            (concat *scheme-gauche-site-repo-path* "/site/lib")
            (mapcar
             #'(lambda (x) (concat x "/lib"))
             (reverse
              (directory-files *scheme-gauche-repo-path* t "^[0-9]")))))))
    (when dir
      (list
       (concat dir "/" file)
       (scheme-with-find-file (concat dir "/" file)
         (let ((env (scheme-current-globals))
               (exports (scheme-current-exports)))
           (if (consp exports)
               (remove-if-not #'(lambda (x) (memq (car x) exports)) env)
             env)))))))

(defun scheme-module-exports/mzscheme (mod)
  (let ((dir (scheme-find-file-in-path
              (symbol-name mod)
              '("."
                "/usr/local/lib/plt/collects"
                "/usr/local/lib/plt/collects/mzlib"))))
    (when dir
      ;; XXXX parse, don't use regexps
      (list
       (concat dir "/" (symbol-name mod))
       (scheme-with-find-file (concat dir "/" (symbol-name mod))
         (when (re-search-forward "(provide" nil t)
           (backward-sexp)
           (backward-char)
           (mapcar #'list (cdr (ignore-errors (scheme-nth-sexp-at-point 0))))
           ))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; This is rather complicated because we to auto-generate docstring
;; summaries from the type information, which means inferring various
;; types from common names.  The benefit is that you don't have to
;; input the same information twice, and can often cut&paste&munge
;; procedure descriptions from the original documentation.

(defun scheme-translate-type (type)
  (if (not (symbolp type))
      type
    (case type
      ((pred proc thunk handler dispatch producer consumer f fn g kons)
       'procedure)
      ((num) 'number)
      ((z) 'complex)
      ((x1 x2 x3 y timeout seconds nanoseconds) 'real)
      ((i j k n m int index size count len length bound nchars start end
        pid uid gid fd fileno errno)
       'integer)
      ((ch) 'char)
      ((str name pattern) 'string)
      ((file path pathname) 'filename)
      ((dir dirname) 'directory)
      ((sym id identifier) 'symbol)
      ((ls lis lst alist lists) 'list)
      ((vec) 'vector)
      ((exc excn err error) 'exception)
      ((ptr) 'pointer)
      ((bool) 'boolean)
      ((env) 'environment)
      ((char string boolean number complex real integer procedure char-set
        port input-port output-port pair list vector array stream hash-table
        thread mutex condition-variable time exception date duration locative
        random-source state condition condition-type queue sequence pointer
        u8vector s8vector u16vector s16vector u32vector s32vector
        u64vector s64vector f32vector f64vector undefined symbol
        block filename directory mmap listener environment non-procedure
        read-table continuation blob generic method class regexp regmatch
        sys-stat fdset)
       type)
      ((parent seed option mode) 'non-procedure)
      (t
       (let* ((str (symbol-name type))
              (i (string-match "-?[0-9]+$" str)))
         (if i
             (scheme-translate-type (intern (substring str 0 i)))
           (let ((i (string-match "-\\([^-]+\\)$" str)))
             (if i
                 (scheme-translate-type (intern (substring str (+ i 1))))
               (if (string-match "\\?$" str)
                   'boolean
                 'object)))))))))

(defun scheme-lookup-type (spec pos)
  (let ((i 1)
        (type nil))
    (while (and (consp spec) (<= i pos))
      (cond
       ((eq :optional (car spec))
        (if (and (= i pos) (consp (cdr spec)))
            (setq type (cadr spec)))
        (setq i (+ pos 1)))
       ((= i pos)
        (setq type (car spec))
        (setq spec nil))
       ((and (consp (cdr spec)) (eq '\.\.\. (cadr spec)))
        (setq type (car spec))
        (setq spec nil)))
      (setq spec (cdr spec))
      (incf i))
    (if type
        (setq type (scheme-translate-type type)))
    type))

(defun scheme-predicate->type (pred)
  (case pred
    ((even? odd?) 'integer)
    ((char-upper-case? char-lower-case?
      char-alphabetic? char-numeric? char-whitespace?)
     'char)
    (t
     ;; catch all the `type?' predicates with pattern matching
     ;; ... we could be smarter if the env was passed
     (let ((str (symbol-name pred)))
       (if (string-match "\\?$" str)
           (scheme-translate-type
            (intern (substring str 0 (- (length str) 1))))
         'object)))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; completion

(eval-when (compile load eval)
  (unless (fboundp 'event-matches-key-specifier-p)
    (defalias 'event-matches-key-specifier-p 'eq)))

(unless (fboundp 'read-event)
  (defun read-event ()
    (aref (read-key-sequence nil) 0)))

(unless (fboundp 'event-basic-type)
  (defalias 'event-basic-type 'event-key))

(defun scheme-string-prefix-p (pref str)
  (let ((p-len (length pref))
        (s-len (length str)))
    (and (<= p-len s-len)
         (equal pref (substring str 0 p-len)))))

(defun scheme-do-completion (str coll &optional strs pred)
  (let* ((coll (mapcar #'(lambda (x)
                           (cond
                            ((symbolp x) (list (symbol-name x)))
                            ((stringp x) (list x))
                            (t x)))
                       coll))
         (completion1 (try-completion str coll pred))
         (completion2 (and strs (try-completion str strs pred)))
         (completion (if (and completion2
                              (or (not completion1)
                                  (< (length completion2)
                                     (length completion1))))
                         completion2
                       completion1)))
    (cond
     ((eq completion t))
     ((not completion)
      (message "Can't find completion for \"%s\"" str)
      (ding))
     ((not (string= str completion))
      (let ((prefix-p (scheme-string-prefix-p completion completion1)))
        (unless prefix-p
          (save-excursion
            (backward-char (length str))
            (insert "\"")))
        (insert (substring completion (length str)))
        (unless prefix-p
          (insert "\"")
          (backward-char))))
     (t
      (let ((win-config (current-window-configuration))
            (done nil))
        (message "Hit space to flush")
        (with-output-to-temp-buffer "*Completions*"
          (display-completion-list
           (sort
            (all-completions str (append strs coll) pred)
            'string-lessp)))
        (while (not done)
          (let* ((orig-event
                  (with-current-buffer (get-buffer "*Completions*")
                    (read-event)))
                 (event (event-basic-type orig-event)))
            (cond
             ((or (event-matches-key-specifier-p event 'tab)
                  (event-matches-key-specifier-p event 9))
              (save-selected-window
                (select-window (get-buffer-window "*Completions*"))
                (if (pos-visible-in-window-p (point-max))
                    (goto-char (point-min))
                  (scroll-up))))
             (t
              (set-window-configuration win-config)
              (if (or (event-matches-key-specifier-p event 'space)
                      (event-matches-key-specifier-p event 32))
                  (bury-buffer (get-buffer "*Completions*"))
                (setq unread-command-events (list orig-event)))
              (setq done t))))))
      ))))

(defun scheme-env-lookup (env sym)
  (let ((spec nil)
        (ls env))
    (while (and ls (not spec))
      (setq spec (assq sym (pop ls))))
    spec))

(defun scheme-current-env ()
  ;; r5rs
  (let ((env (list *scheme-r5rs-info*)))
    ;; base language
    (let ((base (cdr (assq (scheme-current-implementation)
                           *scheme-implementation-exports*))))
      (if base (push base env)))
    ;; imports
    (let ((imports (ignore-errors (scheme-current-imports))))
      (if imports (push imports env)))
    ;; top-level defs
    (let ((top (ignore-errors (scheme-current-globals))))
      (if top (push top env)))
    ;; current local vars
    (let ((locals (ignore-errors (scheme-current-local-vars env))))
      (if locals (push locals env)))
    env))

(defun scheme-env-filter (pred env)
  (mapcar #'car
          (apply #'concatenate
                 'list
                 (mapcar #'(lambda (e) (remove-if-not pred e))
                         env))))

;; checking return values:
;;   a should be capable of returning instances of b
(defun scheme-type-match-p (a b)
  (let ((a1 (scheme-translate-type a))
        (b1 (scheme-translate-type b)))
    (and (not (eq a1 'undefined))   ; check a *does* return something
         (or (eq a1 b1)             ; and they're the same
             (eq a1 'object)        ; ... or a can return anything
             (eq b1 'object)        ; ... or b can receive anything
             (if (symbolp a1)
                 (if (symbolp b1)
                     (case a1           ; ... or the types overlap
                       ((number complex real rational integer)
                        (memq b1 '(number complex real rational integer)))
                       ((port input-port output-port)
                        (memq b1 '(port input-port output-port)))
                       ((pair list)
                        (memq b1 '(pair list)))
                       ((non-procedure)
                        (not (eq 'procedure b1))))
                   (and
                    (consp b1)
                    (if (eq 'or (car b1))
                        ;; type unions
                        (find-if
                         #'(lambda (x)
                             (scheme-type-match-p
                              a1 (scheme-translate-type x)))
                         (cdr b1))
                      (let ((b2 (scheme-translate-special-type b1)))
                        (and (not (equal b1 b2))
                             (scheme-type-match-p a1 b2))))))
               (and (consp a1)
                    ;; type unions
                    (if (eq 'or (car a1))
                        (find-if
                         #'(lambda (x)
                             (scheme-type-match-p (scheme-translate-type x) b1))
                         (cdr a1))
                      ;; other special types
                      (let ((a2 (scheme-translate-special-type a1))
                            (b2 (scheme-translate-special-type b1)))
                        (and (or (not (equal a1 a2)) (not (equal b1 b2)))
                             (scheme-type-match-p a2 b2))))
                    ))))))

(defun scheme-translate-special-type (x)
  (if (not (consp x))
      x
    (case (car x)
      ((list string) (car x))
      ((set special) (cadr x))
      ((flags) 'integer)
      (t x))))

(defun scheme-nth* (n ls)
  (while (and (consp ls) (> n 0))
    (setq n (- n 1)
          ls (cdr ls)))
  (and (consp ls) (car ls)))

(defun scheme-file->lines (file)
  (and (file-readable-p file)
       (scheme-with-find-file file
         (goto-char (point-min))
         (let ((res '()))
           (while (not (eobp))
             (let ((start (point)))
               (forward-line)
               (push (buffer-substring-no-properties start (- (point) 1))
                     res)))
           (reverse res)))))

(defun scheme-passwd-file-names (file &optional pat)
  (delete
   nil
   (mapcar
    #'(lambda (line)
        (and (not (string-match "^[ 	]*#" line))
             (or (not pat) (string-match pat line))
             (string-match "^\\([^:]*\\):" line)
             (match-string 1 line)))
    (scheme-file->lines file))))

(defun scheme-host-file-names (file)
  (scheme-append-map
   #'(lambda (line)
       (let ((i (string-match "#" line)))
         (if i (setq line (substring line 0 i))))
       (cdr (split-string line)))
   (scheme-file->lines file)))

(defun scheme-ssh-known-hosts-file-names (file)
  (scheme-append-map
   #'(lambda (line)
       (split-string (car (split-string line)) ","))
   (scheme-file->lines file)))

(defun scheme-ssh-config-file-names (file)
  (scheme-append-map
   #'(lambda (line)
       (and (string-match "^ *Host" line)
            (cdr (split-string line))))
   (scheme-file->lines file)))

(defun scheme-complete-user-name (trans sym)
  (if (string-match "apple" (emacs-version))
      (append (scheme-passwd-file-names "/etc/passwd" "^[^_].*")
              (delete "Shared" (directory-files "/Users" nil "^[^.].*")))
    (scheme-passwd-file-names "/etc/passwd")))

(defun scheme-complete-host-name (trans sym)
  (append (scheme-host-file-names "/etc/hosts")
          (scheme-ssh-known-hosts-file-names "~/.ssh/known_hosts")
          (scheme-ssh-config-file-names "~/.ssh/config")))

;; my /etc/services is 14k lines, so we try to optimize this
(defun scheme-complete-port-name (trans sym)
  (and (file-readable-p "/etc/services")
       (scheme-with-find-file "/etc/services"
         (goto-char (point-min))
         (let ((rx (concat "^\\(" (regexp-quote (if (symbolp sym)
                                                    (symbol-name sym)
                                                  sym))
                           "[^ 	]*\\)"))
               (res '()))
           (while (not (eobp))
             (if (not (re-search-forward rx nil t))
                 (goto-char (point-max))
               (let ((str (match-string-no-properties 1)))
                 (if (not (equal str (car res)))
                     (push str res)))
               (forward-char 1)))
           res))))

(defun scheme-complete-file-name (trans sym)
  (let* ((file (file-name-nondirectory sym))
         (dir (file-name-directory sym))
         (res (file-name-all-completions file (or dir "."))))
    (if dir
        (mapcar #'(lambda (f) (concat dir f)) res)
      res)))

(defun scheme-complete-directory-name (trans sym)
  (let* ((file (file-name-nondirectory sym))
         (dir (file-name-directory sym))
         (res (file-name-all-completions file (or dir ".")))
         (res2 (if dir (mapcar #'(lambda (f) (concat dir f)) res) res)))
    (remove-if-not #'file-directory-p res2)))

(defun scheme-string-completer (type)
  (case type
    ((filename)
     '(scheme-complete-file-name file-name-nondirectory))
    ((directory)
     '(scheme-complete-directory-name file-name-nondirectory))
    (t
     (cond
      ((and (consp type) (eq 'string (car type)))
       (cadr type))
      ((and (consp type) (eq 'or (car type)))
       (car (delete nil (mapcar #'scheme-string-completer (cdr type)))))))))

(defun scheme-apply-string-completer (cmpl sym)
  (let ((func (if (consp cmpl) (car cmpl) cmpl))
        (trans (and (consp cmpl) (cadr cmpl))))
    (funcall func trans sym)))

(defun scheme-smart-complete (&optional arg)
  (interactive "P")
  (let* ((end (point))
         (start (save-excursion (skip-syntax-backward "w_") (point)))
         (sym (buffer-substring-no-properties start end))
         (in-str-p (scheme-in-string-p))
         (x (save-excursion
              (if in-str-p (scheme-beginning-of-string))
              (scheme-enclosing-2-sexp-prefixes)))
         (inner-proc (car x))
         (inner-pos (cadr x))
         (outer-proc (caddr x))
         (outer-pos (cadddr x))
         (env (save-excursion
                (if in-str-p (scheme-beginning-of-string))
                (scheme-current-env)))
         (outer-spec (scheme-env-lookup env outer-proc))
         (outer-type (scheme-translate-type (cadr outer-spec)))
         (inner-spec (scheme-env-lookup env inner-proc))
         (inner-type (scheme-translate-type (cadr inner-spec))))
    (cond
     ;; return all env symbols when a prefix arg is given
     (arg
      (scheme-do-completion sym (scheme-env-filter #'(lambda (x) t) env)))
     ;; for now just do file-name completion in strings
     (in-str-p
      (let* ((param-type
              (and (consp inner-type)
                   (eq 'lambda (car inner-type))
                   (scheme-lookup-type (cadr inner-type) inner-pos)))
             (completer (or (scheme-string-completer param-type)
                            '(scheme-complete-file-name
                              file-name-nondirectory))))
        (scheme-do-completion
         ;;(if (consp completer) (funcall (cadr completer) sym) sym)
         sym
         (scheme-apply-string-completer completer sym))))
     ;; outer special
     ((and (consp outer-type)
           (eq 'special (car outer-type))
           (cadddr outer-type))
      (scheme-do-completion sym (funcall (cadddr outer-type) sym)))
     ;; inner special
     ((and (consp inner-type)
           (eq 'special (car inner-type))
           (caddr inner-type))
      (scheme-do-completion sym (funcall (caddr inner-type) sym)))
     ;; completing inner procedure, complete procedures with a
     ;; matching return type
     ((and (consp outer-type)
           (eq 'lambda (car outer-type))
           (not (zerop outer-pos))
           (scheme-nth* (- outer-pos 1) (cadr outer-type))
           (or (zerop inner-pos)
               (and (>= 1 inner-pos)
                    (consp inner-type)
                    (eq 'lambda (car inner-type))
                    (let ((param-type
                           (scheme-lookup-type (cadr inner-type) inner-pos)))
                      (and (consp param-type)
                           (eq 'lambda (car param-type))
                           (eq (caddr inner-type) (caddr param-type)))))))
      (let ((want-type (scheme-lookup-type (cadr outer-type) outer-pos)))
        (scheme-do-completion
         sym
         (scheme-env-filter
          #'(lambda (x)
              (let ((type (cadr x)))
                (or (memq type '(procedure object nil))
                    (and (consp type)
                         (or (and (eq 'syntax (car type))
                                  (not (eq 'undefined (caddr type))))
                             (and (eq 'lambda (car type))
                                  (scheme-type-match-p (caddr type)
                                                       want-type)))))))
          env))))
     ;; completing a normal parameter
     ((and inner-proc
           (not (zerop inner-pos))
           (consp inner-type)
           (eq 'lambda (car inner-type)))
      (let* ((param-type (scheme-lookup-type (cadr inner-type) inner-pos))
             (set-or-flags
              (or (and (consp param-type)
                       (case (car param-type)
                         ((set) (cddr param-type))
                         ((flags) (cdr param-type))))
                  ;; handle nested arithmetic functions inside a flags
                  ;; parameter
                  (and (not (zerop outer-pos))
                       (consp outer-type)
                       (eq 'lambda (car outer-type))
                       (let ((outer-param-type
                              (scheme-lookup-type (cadr outer-type)
                                                  outer-pos)))
                         (and (consp outer-param-type)
                              (eq 'flags (car outer-param-type))
                              (memq (scheme-translate-type param-type)
                                    '(number complex real rational integer))
                              (memq (scheme-translate-type (caddr inner-type))
                                    '(number complex real rational integer))
                              (cdr outer-param-type))))))
             (base-type (if set-or-flags
                            (if (and (consp param-type)
                                     (eq 'set (car param-type)))
                                (scheme-translate-type (cadr param-type))
                              'integer)
                            param-type))
             (base-completions
              (scheme-env-filter
               #'(lambda (x)
                   (scheme-type-match-p (cadr x) base-type))
               env))
             (str-completions
              (let ((completer (scheme-string-completer base-type)))
                (and
                 completer
                 (scheme-apply-string-completer completer sym)))))
        (scheme-do-completion
         sym
         (append set-or-flags base-completions)
         str-completions)))
     ;; completing a function
     ((zerop inner-pos)
      (scheme-do-completion
       sym
       (scheme-env-filter
        #'(lambda (x)
            (or (null (cdr x))
                (memq (cadr x) '(procedure object nil))
                (and (consp (cadr x))
                     (memq (caadr x) '(lambda syntax)))))
        env)))
     ;; complete everything
     (t
      (scheme-do-completion sym (scheme-env-filter #'(lambda (x) t) env)) ))))

(defun scheme-complete-or-indent (&optional arg)
  (interactive "P")
  (let* ((end (point))
         (func
          (save-excursion
            (beginning-of-line)
            (if (re-search-forward "\\S-" end t)
                'scheme-smart-complete
              'lisp-indent-line))))
    (funcall func arg)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; optional indentation handling

(defvar calculate-lisp-indent-last-sexp)

;; Copied from scheme-indent-function, but ignore
;; scheme-indent-function property for local variables.
(defun scheme-smart-indent-function (indent-point state)
  (let ((normal-indent (current-column)))
    (goto-char (1+ (elt state 1)))
    (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
    (if (and (elt state 2)
             (not (looking-at "\\sw\\|\\s_")))
        ;; car of form doesn't seem to be a symbol
        (progn
          (if (not (> (save-excursion (forward-line 1) (point))
                      calculate-lisp-indent-last-sexp))
              (progn (goto-char calculate-lisp-indent-last-sexp)
                     (beginning-of-line)
                     (parse-partial-sexp (point)
					 calculate-lisp-indent-last-sexp 0 t)))
          ;; Indent under the list or under the first sexp on the same
          ;; line as calculate-lisp-indent-last-sexp.  Note that first
          ;; thing on that line has to be complete sexp since we are
          ;; inside the innermost containing sexp.
          (backward-prefix-chars)
          (current-column))
      (let* ((function (buffer-substring (point)
                                         (progn (forward-sexp 1) (point))))
             (function-sym (intern-soft function))
             (method (and (not (assq function-sym (scheme-current-local-vars)))
                          (get function-sym 'scheme-indent-function))))
	(cond ((or (eq method 'defun)
		   (and (null method)
			(> (length function) 3)
			(string-match "\\`def" function)))
	       (lisp-indent-defform state indent-point))
	      ((integerp method)
	       (lisp-indent-specform method state
				     indent-point normal-indent))
	      (method
               (funcall method state indent-point normal-indent)))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; optional eldoc function

(defun scheme-translate-dot-to-optional (ls)
  (let ((res '()))
    (while (consp ls)
      (setq res (cons (car ls) res))
      (setq ls (cdr ls)))
    (if (not (null ls))
        (setq res (cons ls (cons :optional res))))
    (reverse res)))

(defun scheme-optional-in-brackets (ls)
  ;; put optional arguments inside brackets (via a vector)
  (if (memq :optional ls)
      (let ((res '()))
        (while (and (consp ls) (not (eq :optional (car ls))))
          (push (pop ls) res))
        (reverse (cons (apply #'vector (cdr ls)) res)))
    ls))

(defun scheme-base-type (x)
  (if (not (consp x))
      x
    (case (car x)
      ((string list) (car x))
      ((set) (or (cadr x) (car x)))
      ((flags) 'integer)
      ((lambda) 'procedure)
      ((syntax) 'syntax)
      (t x))))

(defun scheme-sexp-to-string (sexp)
  (with-output-to-string (princ sexp)))

(defun scheme-get-current-symbol-info ()
  (let* ((sym (eldoc-current-symbol))
         (fnsym0 (eldoc-fnsym-in-current-sexp))
         (fnsym (if (consp fnsym0) (car fnsym0) fnsym0))
         (env (save-excursion
                (if (scheme-in-string-p) (scheme-beginning-of-string))
                (scheme-current-env)))
         (spec (or (and sym (scheme-env-lookup env sym))
                   (and fnsym (scheme-env-lookup env fnsym)))))
    (and (consp spec)
         (consp (cdr spec))
         (let ((type (cadr spec)))
           (concat
            (cond
             ((nth 3 spec)
              "")
             ((and (consp type)
                   (memq (car type) '(syntax lambda)))
              (concat
               (if (eq (car type) 'syntax)
                   "syntax: "
                 "")
               (scheme-sexp-to-string
                (cons (car spec)
                      (scheme-optional-in-brackets
                       (mapcar #'scheme-base-type
                               (scheme-translate-dot-to-optional
                                (cadr type))))))
               (if (and (consp (cddr type))
                        (not (memq (caddr type) '(obj object))))
                   (concat " => " (scheme-sexp-to-string (caddr type)))
                 "")))
             ((and (consp type) (eq (car type) 'special))
              (scheme-sexp-to-string (car spec)))
             (t
              (scheme-sexp-to-string type)))
            (if (and (not (nth 3 spec)) (nth 4 spec)) " - " "")
            (or (nth 4 spec) ""))))))

(provide 'scheme-complete)

;; Local Variables:
;; eval: (put 'scheme-with-find-file 'lisp-indent-hook 1)
;; End:

